From 06cb35276edeea183d06ac8b87bf52de9340caf5 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 8 Feb 2021 16:33:11 +0100 Subject: [PATCH 01/14] removed burst crc the burst CRC is not needed, because we only receive frames with correct CRC. So its more important to create a correct ARQ algorithm. The 2byte CRC has been removed bei 2 x CRC8 for DX call sign and own callsign --- arq.py | 142 ++++++++++++++++++++++++++---------------------------- modem.py | 12 ++++- static.py | 13 ++++- 3 files changed, 89 insertions(+), 78 deletions(-) diff --git a/arq.py b/arq.py index 3e820c19..c99963d6 100644 --- a/arq.py +++ b/arq.py @@ -16,6 +16,7 @@ import modem import helpers import main + modem = modem.RF() static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 3 #6?! @@ -26,8 +27,6 @@ def arq_ack_timeout(): def data_received(data_in): - - # arqframe = frame_type + \ # 1 [:1] # frame type and current number of arq frame of (current) burst # bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ # 1 [1:2] # total number of arq frames per (current) burst # static.ARQ_N_CURRENT_ARQ_FRAME + \ # 2 [2:4] # current arq frame number @@ -35,8 +34,7 @@ def data_received(data_in): # static.ARQ_BURST_PAYLOAD_CRC + \ # 2 [6:8] # arq crc # payload_data # N [8:N] # payload data - - + static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame static.ARQ_N_RX_FRAMES_PER_BURSTS = int.from_bytes(bytes(data_in[1:2]), "big") #get number of bursts from received frame static.ARQ_RX_N_CURRENT_ARQ_FRAME = int.from_bytes(bytes(data_in[2:4]), "big") #get current number of total frames @@ -58,7 +56,7 @@ def data_received(data_in): logging.info("ARQ | RX | ARQ FRAME [" + str(static.ARQ_N_FRAME) + "/" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS) + "] [" + str(arq_percent_burst).zfill(3) + "%] --- TOTAL [" + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME) + "/" + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) + "] [" + str(arq_percent_frame).zfill(3) + "%]" ) - + #allocate ARQ_RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a data frame to N list position so we can explicit search for it @@ -66,16 +64,13 @@ def data_received(data_in): for i in range(0,static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME+1): static.ARQ_RX_FRAME_BUFFER.insert(i,None) - #allocate ARQ_RX_BURST_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a burst to N list position so we can explicit search for it if static.ARQ_N_RX_FRAMES_PER_BURSTS != len(static.ARQ_RX_BURST_BUFFER) and static.ARQ_N_FRAME == 1: for i in range(0,static.ARQ_N_RX_FRAMES_PER_BURSTS+1): static.ARQ_RX_BURST_BUFFER.insert(i,None) - - - + # now we add the incoming data to the specified position in our lists static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) @@ -85,41 +80,54 @@ def data_received(data_in): # run only if we recieved all ARQ FRAMES per ARQ BURST burst_total_payload = bytearray() - if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS: #if received bursts are equal to burst number in frame + if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) == 1: #if received bursts are equal to burst number in frame - #here we get the total payload for the frame to calculate the crc - for n_raw_frame in range(1,len(static.ARQ_RX_BURST_BUFFER)): - # we need to check if we have a None or received data in list - if static.ARQ_RX_BURST_BUFFER[n_raw_frame] != None: - burst_frame = static.ARQ_RX_BURST_BUFFER[n_raw_frame] #get burst frame - burst_payload = burst_frame[8:] #remove frame type and burst CRC #4 - burst_total_payload = burst_total_payload + burst_payload #stick bursts together +# #here we get the total payload for the frame to calculate the crc +# for n_raw_frame in range(1,len(static.ARQ_RX_BURST_BUFFER)): +# # we need to check if we have a None or received data in list +# if static.ARQ_RX_BURST_BUFFER[n_raw_frame] != None: +# burst_frame = static.ARQ_RX_BURST_BUFFER[n_raw_frame] #get burst frame +# burst_payload = burst_frame[8:] #remove frame type and burst CRC #4 +# burst_total_payload = burst_total_payload + burst_payload #stick bursts together # ------------------ calculate CRC of BURST - burst_payload_crc = helpers.get_crc_16(burst_total_payload) +# burst_payload_crc = helpers.get_crc_16(burst_total_payload) # IF BURST CRC IS CORRECT, APPEND BURST TO BUFFER AND SEND ACK FRAME - if burst_payload_crc == data_in[6:8]: +# if burst_payload_crc == data_in[6:8]: #BUILDING ACK FRAME FOR BURST ----------------------------------------------- - #ack_payload = bytes(burst_payload_crc) - ack_frame = b'<'+ bytes(burst_payload_crc) # < = 60 - ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) - ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send +# #ack_payload = bytes(burst_payload_crc) +# ack_frame = b'<'+ bytes(burst_payload_crc) # < = 60 +# ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) +# ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- - logging.info("ARQ | TX | ARQ BURST ACK [" + str(data_in[6:8].hex()) +"]") - modem.transmit_arq_ack(ack_buffer) +# logging.info("ARQ | TX | ARQ BURST ACK [" + str(data_in[6:8].hex()) +"]") +# modem.transmit_arq_ack(ack_buffer) # ---------------------------------------------------------------- - static.ARQ_RX_BURST_BUFFER = [] # CLEAR RX BURST BUFFER AFTER SENDING DATA +# static.ARQ_RX_BURST_BUFFER = [] # CLEAR RX BURST BUFFER AFTER SENDING DATA - else: #IF burst payload crc and input crc are NOT equal - logging.info("ARQ BURST CRC NOT EQUAL! [" + str(data_in[6:8]) + "]") - static.ARQ_RX_BURST_BUFFER = [] #erase ARQ RX Burst buffer +# else: #IF burst payload crc and input crc are NOT equal +# logging.info("ARQ BURST CRC NOT EQUAL! [" + str(data_in[6:8]) + "]") +# static.ARQ_RX_BURST_BUFFER = [] #erase ARQ RX Burst buffer - #if nframes are unequal to expected frames per burst + + # --------------- CHECK IF WE ARE MISSING FRAMES ------------------------------------------- + for burst in range(1,len(static.ARQ_RX_BURST_BUFFER)): + if static.ARQ_RX_BURST_BUFFER[burst] == None: + print("Missing frames:" + str(burst)) + + + + + logging.info("ARQ | TX | ARQ BURST ACK") + ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) + modem.transmit_arq_ack(ack_buffer) + static.ARQ_RX_BURST_BUFFER = [] + + #if nframes are unequal to expected frames per burst #just a placeholder at this time else: - #just a placeholder at this time pass # ---------------------------- FRAME MACHINE @@ -153,8 +161,7 @@ def data_received(data_in): arq_frame_payload = arq_frame_payload[0] - # --------- AFTER WE SEPARATED BOF AND EOF, STICK EVERYTHING TOGETHER - + # --------- AFTER WE SEPARATED BOF AND EOF, STICK EVERYTHING TOGETHER complete_data_frame = complete_data_frame + arq_frame_payload @@ -166,10 +173,9 @@ def data_received(data_in): #IF THE FRAME PAYLOAD CRC IS EQUAL TO THE FRAME CRC WHICH IS KNOWN FROM THE HEADER --> SUCCESS if frame_payload_crc == static.FRAME_CRC: logging.info("ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED! - TIME TO PARTY") - + #append received frame to RX_BUFFER static.RX_BUFFER.append(complete_data_frame) - - + #BUILDING ACK FRAME FOR DATA FRAME ----------------------------------------------- ack_frame = b'='+ bytes(static.FRAME_CRC) # < = 61 @@ -208,31 +214,22 @@ def frame_ack_received(): static.ARQ_FRAME_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame - def transmit(data_out): static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 8 #3 ohne ARQ_TX_N_FRAMES_PER_BURST frame_header_length = 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) # aufrunden 3.2 = 4 - - #print(static.FREEDV_DATA_PAYLOAD_PER_FRAME) - #print(static.ARQ_PAYLOAD_PER_FRAME) - #print(n_bursts_prediction) - ####static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = n_arq_frames_per_data_frame.to_bytes(2, byteorder='big') #65535 + + 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) frame_payload_crc = helpers.get_crc_16(data_out) - #print(frame_payload_crc) - + # This is the total frame with frame header, which will be send data_out = frame_payload_crc + static.FRAME_BOF + data_out + static.FRAME_EOF # 2 2 N 2 - # --------------------------------------------- LETS CREATE A BUFFER BY SPLITTING THE FILES INTO PEACES static.TX_BUFFER = [data_out[i:i+static.ARQ_PAYLOAD_PER_FRAME] for i in range(0, len(data_out), static.ARQ_PAYLOAD_PER_FRAME)] static.TX_BUFFER_SIZE = len(static.TX_BUFFER) - #print(static.TX_BUFFER) logging.info("ARQ | TX | DATA FRAME --- BYTES: " + str(len(data_out)) + " ARQ FRAMES: " + str(static.TX_BUFFER_SIZE)) @@ -241,51 +238,46 @@ def transmit(data_out): static.ARQ_N_SENT_FRAMES = 0 # SET N SENT FRAMES TO 0 FOR A NEW SENDING CYCLE while static.ARQ_N_SENT_FRAMES <= static.TX_BUFFER_SIZE: - #print("static.ARQ_N_SENT_FRAMES: " + str(static.ARQ_N_SENT_FRAMES)) static.ARQ_TX_N_FRAMES_PER_BURST = get_n_frames_per_burst() # ----------- CREATE FRAME TOTAL PAYLOAD TO BE ABLE TO CREATE CRC FOR IT - burst_total_payload = bytearray() + try: # DETECT IF LAST BURST TO PREVENT INDEX ERROR OF BUFFER - for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): # Loop through TX_BUFFER LIST - # make sure we have always a filled buffer with the length of payload per frame - burst_raw_payload = static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i] - burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME) - burst_payload[:len(burst_raw_payload)] = burst_raw_payload # get frame from TX_BUFFER - burst_total_payload = burst_total_payload + burst_payload # append single frame to total payload buffer - + for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): # Loop through TX_BUFFER LIST + len(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i]) #we calculate the length to trigger a list index error + except IndexError: # IF LAST BURST DETECTED BUILD CRC WITH LESS FRAMES AND SET static.ARQ_TX_N_FRAMES_PER_BURST TO VALUE OF REST! - burst_total_payload = bytearray() # reset burst_total_payload because of possible input remaining of detecting loop one step above if static.ARQ_N_SENT_FRAMES == 0 and (static.ARQ_TX_N_FRAMES_PER_BURST > static.TX_BUFFER_SIZE): #WE CANT DO MODULO 0 --> CHECK IF FIRST FRAME == LAST FRAME static.ARQ_TX_N_FRAMES_PER_BURST = static.TX_BUFFER_SIZE + elif static.ARQ_N_SENT_FRAMES == 1 and (static.ARQ_TX_N_FRAMES_PER_BURST > static.TX_BUFFER_SIZE): # MODULO 1 WILL ALWAYS BE 0 --> THIS FIXES IT static.ARQ_TX_N_FRAMES_PER_BURST = static.TX_BUFFER_SIZE - static.ARQ_N_SENT_FRAMES + else: static.ARQ_TX_N_FRAMES_PER_BURST = (static.TX_BUFFER_SIZE % static.ARQ_N_SENT_FRAMES) - - #print("ARQ_TX_N_FRAMES_PER_BURST OF LAST BURST: " + str(static.ARQ_TX_N_FRAMES_PER_BURST)) - - for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): #bytearray(b'111111111111111111111111222222222222222222222222') - - # make sure we have always a filled buffer with the length of payload per frame - burst_raw_payload = static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i] - burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME) - burst_payload[:len(burst_raw_payload)] = burst_raw_payload # get frame from TX_BUFFER - burst_total_payload = burst_total_payload + burst_payload # append single frame to total payload buffer - - # ----------- GENERATE PAYLOAD CRC FOR ARQ_TX_N_FRAMES_PER_BURST - static.ARQ_BURST_PAYLOAD_CRC = helpers.get_crc_16(burst_total_payload) + + +# burst_total_payload = bytearray() # reset burst_total_payload because of possible input remaining of detecting loop one step above +# for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): #bytearray(b'111111111111111111111111222222222222222222222222') +# +# # make sure we have always a filled buffer with the length of payload per frame +# burst_raw_payload = static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i] +# burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME) +# burst_payload[:len(burst_raw_payload)] = burst_raw_payload # get frame from TX_BUFFER +# burst_total_payload = burst_total_payload + burst_payload # append single frame to total payload buffer +# +# # ----------- GENERATE PAYLOAD CRC FOR ARQ_TX_N_FRAMES_PER_BURST +# static.ARQ_BURST_PAYLOAD_CRC = helpers.get_crc_16(burst_total_payload) #--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK RECEPTION FAILS for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES): if static.ARQ_N_SENT_FRAMES+1 <= static.TX_BUFFER_SIZE: - logging.info("ARQ | TX | B:[" + str(static.ARQ_BURST_PAYLOAD_CRC.hex()) + "] 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.info("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) + "]") + # lets start a thread to transmit nonblocking TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") TRANSMIT_ARQ_BURST_THREAD.start() @@ -334,7 +326,7 @@ def transmit(data_out): # ----------- if no ACK received and out of retries.....stop frame sending if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_FRAME_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: logging.info("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") - print(bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES])) + break #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK diff --git a/modem.py b/modem.py index 5b55fdfa..6355ea27 100644 --- a/modem.py +++ b/modem.py @@ -19,6 +19,11 @@ import helpers import static import arq + + + + + class RF(): def __init__(self): @@ -179,11 +184,13 @@ class RF(): # 2 # arq crc # N # payload data + arqframe = frame_type + \ bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ static.ARQ_TX_N_CURRENT_ARQ_FRAME + \ static.ARQ_TX_N_TOTAL_ARQ_FRAMES + \ - static.ARQ_BURST_PAYLOAD_CRC + \ + static.MYCALLSIGN_CRC8 + \ + static.DXCALLSIGN_CRC8 + \ payload_data #print(arqframe) @@ -292,8 +299,9 @@ class RF(): frametype = int.from_bytes(bytes(data_bytes_out[:1]), "big") frame = frametype - 10 n_frames_per_burst = int.from_bytes(bytes(data_bytes_out[1:2]), "big") - if 50 >= frametype >= 10 and len(data_bytes_out) > 30: # --> The length check filters out random strings without CRC + if 50 >= frametype >= 10 and len(data_bytes_out) > 30: # --> The length check filters out random strings without CRC arq.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16 + else: print("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out))) diff --git a/static.py b/static.py index 90555be3..176c01e7 100644 --- a/static.py +++ b/static.py @@ -12,10 +12,21 @@ Created on Wed Dec 23 11:13:57 2020 #MODULATION TIME: 0.004580974578857422 #12 # 2 FRAME + PREAMBLE #AUDIO TIME: 14.750595331192017 #12 # 2 FRAME + PREAMBLE + +MYCALLSIGN = b'' +MYCALLSIGN_CRC8 = b'' + +DXCALLSIGN = b'' +DXCALLSIGN_CRC8 = b'' + + + + + # FreeDV Defaults FREEDV_RECEIVE = True -FREEDV_DATA_MODE = 12 +FREEDV_DATA_MODE = 10 FREEDV_SIGNALLING_MODE = 14 FREEDV_DATA_BYTES_PER_FRAME = 0 From eb7f98e2e184e54fa0685172ce7abe9028270990 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 8 Feb 2021 19:00:12 +0100 Subject: [PATCH 02/14] RPT FRAME first bleeding edge attempt not completed yet --- arq.py | 185 +++++++++++++++++++++++++++++++++++------------------- modem.py | 137 +++++++++++++++++++++++++++------------- static.py | 6 ++ 3 files changed, 219 insertions(+), 109 deletions(-) diff --git a/arq.py b/arq.py index c99963d6..621601d8 100644 --- a/arq.py +++ b/arq.py @@ -27,6 +27,13 @@ def arq_ack_timeout(): def data_received(data_in): + + static.ARQ_RX_TIMEOUT = time.time() + static.ARQ_RX_TIMEOUT_SECONDS + while time.time() < static.ARQ_RX_TIMEOUT: + + + + # arqframe = frame_type + \ # 1 [:1] # frame type and current number of arq frame of (current) burst # bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ # 1 [1:2] # total number of arq frames per (current) burst # static.ARQ_N_CURRENT_ARQ_FRAME + \ # 2 [2:4] # current arq frame number @@ -34,8 +41,14 @@ def data_received(data_in): # static.ARQ_BURST_PAYLOAD_CRC + \ # 2 [6:8] # arq crc # payload_data # N [8:N] # payload data - - static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame + + # detect if we got a RPT frame + if int.from_bytes(bytes(data_in[:1]), "big") == 51: + frame_type = int.from_bytes(bytes(data_in[:1]), "big") + else: + frame_type = 10 + static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame + static.ARQ_N_RX_FRAMES_PER_BURSTS = int.from_bytes(bytes(data_in[1:2]), "big") #get number of bursts from received frame static.ARQ_RX_N_CURRENT_ARQ_FRAME = int.from_bytes(bytes(data_in[2:4]), "big") #get current number of total frames static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = int.from_bytes(bytes(data_in[4:6]), "big") # get get total number of frames @@ -61,12 +74,14 @@ def data_received(data_in): #allocate ARQ_RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a data frame to N list position so we can explicit search for it if static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME != len(static.ARQ_RX_FRAME_BUFFER) and static.ARQ_RX_N_CURRENT_ARQ_FRAME == 1: + static.ARQ_RX_FRAME_BUFFER = [] for i in range(0,static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME+1): static.ARQ_RX_FRAME_BUFFER.insert(i,None) #allocate ARQ_RX_BURST_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a burst to N list position so we can explicit search for it - if static.ARQ_N_RX_FRAMES_PER_BURSTS != len(static.ARQ_RX_BURST_BUFFER) and static.ARQ_N_FRAME == 1: + if static.ARQ_N_RX_FRAMES_PER_BURSTS != len(static.ARQ_RX_BURST_BUFFER) and static.ARQ_N_FRAME == 1 and frame_type != 51: + static.ARQ_RX_BURST_BUFFER = [] for i in range(0,static.ARQ_N_RX_FRAMES_PER_BURSTS+1): static.ARQ_RX_BURST_BUFFER.insert(i,None) @@ -74,62 +89,60 @@ def data_received(data_in): # now we add the incoming data to the specified position in our lists static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) - + # -------------------------- ARQ BURST CHECKER # run only if we recieved all ARQ FRAMES per ARQ BURST - burst_total_payload = bytearray() if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) == 1: #if received bursts are equal to burst number in frame + + logging.info("ARQ | TX | BURST ACK") -# #here we get the total payload for the frame to calculate the crc -# for n_raw_frame in range(1,len(static.ARQ_RX_BURST_BUFFER)): -# # we need to check if we have a None or received data in list -# if static.ARQ_RX_BURST_BUFFER[n_raw_frame] != None: -# burst_frame = static.ARQ_RX_BURST_BUFFER[n_raw_frame] #get burst frame -# burst_payload = burst_frame[8:] #remove frame type and burst CRC #4 -# burst_total_payload = burst_total_payload + burst_payload #stick bursts together - - # ------------------ calculate CRC of BURST -# burst_payload_crc = helpers.get_crc_16(burst_total_payload) - # IF BURST CRC IS CORRECT, APPEND BURST TO BUFFER AND SEND ACK FRAME -# if burst_payload_crc == data_in[6:8]: - - #BUILDING ACK FRAME FOR BURST ----------------------------------------------- -# #ack_payload = bytes(burst_payload_crc) -# ack_frame = b'<'+ bytes(burst_payload_crc) # < = 60 -# ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) -# ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send + #BUILDING ACK FRAME FOR BURST ----------------------------------------------- + ack_payload = b'ACK FRAME' + ack_frame = b'<' + ack_payload # < = 60 + ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) + ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send - #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- -# logging.info("ARQ | TX | ARQ BURST ACK [" + str(data_in[6:8].hex()) +"]") -# modem.transmit_arq_ack(ack_buffer) - - # ---------------------------------------------------------------- -# static.ARQ_RX_BURST_BUFFER = [] # CLEAR RX BURST BUFFER AFTER SENDING DATA - -# else: #IF burst payload crc and input crc are NOT equal -# logging.info("ARQ BURST CRC NOT EQUAL! [" + str(data_in[6:8]) + "]") -# static.ARQ_RX_BURST_BUFFER = [] #erase ARQ RX Burst buffer - - - # --------------- CHECK IF WE ARE MISSING FRAMES ------------------------------------------- - for burst in range(1,len(static.ARQ_RX_BURST_BUFFER)): - if static.ARQ_RX_BURST_BUFFER[burst] == None: - print("Missing frames:" + str(burst)) - - - - - logging.info("ARQ | TX | ARQ BURST ACK") - ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) + #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- modem.transmit_arq_ack(ack_buffer) + + #clear burst buffer static.ARQ_RX_BURST_BUFFER = [] - #if nframes are unequal to expected frames per burst #just a placeholder at this time - else: - pass + #if decoded N frames are unequal to expected frames per burst + elif static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) != 1: + print("RPT FRAME NEEDS TO BE SEND!!!!") + # --------------- CHECK WHICH BURST FRAMES WE ARE MISSING ------------------------------------------- + + missing_frames = b'' + for burst in range(1,len(static.ARQ_RX_BURST_BUFFER)): + + if static.ARQ_RX_BURST_BUFFER[burst] == None: + print(burst) + burst = burst.to_bytes(2, byteorder='big') + missing_frames += burst + + + print("MISSING FRAMES: " + str(missing_frames)) + + rpt_payload = missing_frames + rpt_frame = b'>' + rpt_payload #> = 63 + rpt_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) + rpt_buffer[:len(rpt_frame)] = rpt_frame # set buffersize to length of data which will be send + modem.transmit_arq_ack(rpt_buffer) + + + + + + + + + + + # ---------------------------- FRAME MACHINE # --------------- CHECK IF WE ARE MISSING FRAMES ------------------------------------------- @@ -163,7 +176,7 @@ def data_received(data_in): # --------- AFTER WE SEPARATED BOF AND EOF, STICK EVERYTHING TOGETHER complete_data_frame = complete_data_frame + arq_frame_payload - + #check if Begin of Frame BOF and End of Frame EOF are received, then start calculating CRC and sticking everything together if static.ARQ_FRAME_BOF_RECEIVED == True and static.ARQ_FRAME_EOF_RECEIVED == True: @@ -199,17 +212,32 @@ def data_received(data_in): else: logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") - + + break def burst_ack_received(): - logging.debug("ARQ | RX | BURST ACK RCVD!") + logging.info("ARQ | RX | BURST ACK RCVD!") static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting static.ARQ_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame +def burst_rpt_received(data_in): + + logging.info("ARQ | RX | BURST RPT RCVD!") + static.ARQ_ACK_TIMEOUT = 0 #Force timer to stop waiting + static.ARQ_ACK_RECEIVED = 0 #Force data loops of TNC to stop and continue with next frame + static.ARQ_RPT_RECEIVED = True + #static.ARQ_RPT_FRAMES = b'123' + missing = 3 + missing = missing.to_bytes(2, byteorder='big') + static.ARQ_RPT_FRAMES.insert(0,missing) + + print(bytes(data_in)) + + def frame_ack_received(): - logging.debug("ARQ | RX | FRAME ACK RCVD!") + logging.info("ARQ | RX | FRAME ACK RCVD!") static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting static.ARQ_FRAME_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame @@ -258,18 +286,6 @@ def transmit(data_out): else: static.ARQ_TX_N_FRAMES_PER_BURST = (static.TX_BUFFER_SIZE % static.ARQ_N_SENT_FRAMES) - -# burst_total_payload = bytearray() # reset burst_total_payload because of possible input remaining of detecting loop one step above -# for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): #bytearray(b'111111111111111111111111222222222222222222222222') -# -# # make sure we have always a filled buffer with the length of payload per frame -# burst_raw_payload = static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + i] -# burst_payload = bytearray(static.ARQ_PAYLOAD_PER_FRAME) -# burst_payload[:len(burst_raw_payload)] = burst_raw_payload # get frame from TX_BUFFER -# burst_total_payload = burst_total_payload + burst_payload # append single frame to total payload buffer -# -# # ----------- GENERATE PAYLOAD CRC FOR ARQ_TX_N_FRAMES_PER_BURST -# static.ARQ_BURST_PAYLOAD_CRC = helpers.get_crc_16(burst_total_payload) #--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK RECEPTION FAILS for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES): @@ -295,16 +311,55 @@ def transmit(data_out): logging.debug("ARQ | RX | WAITING FOR BURST ACK") static.ARQ_STATE = 'RECEIVING_ACK' + timer = threading.Timer(static.ARQ_ACK_TIMEOUT_SECONDS, arq_ack_timeout) timer.start() # --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN - while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_ACK_RECEIVED == 0: + while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_RPT_RECEIVED == False and static.ARQ_ACK_RECEIVED == 0: time.sleep(0.01) # lets reduce CPU load a little bit #print(static.ARQ_STATE) + + + #-------------------------------------------------------------------------------------------------------------- + + if static.ARQ_RPT_RECEIVED == True: + print("lets send a rpt packet") + TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") + TRANSMIT_ARQ_BURST_THREAD.start() + # lets wait during sending. After sending is finished we will continue + while static.ARQ_STATE == 'SENDING_DATA': + time.sleep(0.05) + + # --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1 + #reset timer and ack state + static.ARQ_FRAME_ACK_RECEIVED = 0 + static.ARQ_ACK_RECEIVED = 0 + static.ARQ_ACK_TIMEOUT = 0 + + logging.debug("ARQ | RX | WAITING FOR BURST ACK") + static.ARQ_STATE = 'RECEIVING_ACK' + + timer = threading.Timer(static.ARQ_ACK_TIMEOUT_SECONDS, arq_ack_timeout) + timer.start() + + while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_RPT_RECEIVED == False and static.ARQ_ACK_RECEIVED == 0: + time.sleep(0.01) # lets reduce CPU load a little bit + #print(static.ARQ_STATE) + + #-------------------------------------------------------------------------------------------------------------- + + + + + + + + + if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: #logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN") diff --git a/modem.py b/modem.py index 6355ea27..f0ca142a 100644 --- a/modem.py +++ b/modem.py @@ -133,7 +133,8 @@ class RF(): txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ txbuffer += bytes(mod_out) txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ - # -------------- transmit audio + + # -------------- transmit audio twice self.stream_tx.write(bytes(txbuffer)) self.stream_tx.write(bytes(txbuffer)) @@ -161,53 +162,91 @@ class RF(): txbuffer += bytes(mod_out_preamble) txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ - for n in range(0,static.ARQ_TX_N_FRAMES_PER_BURST): + if static.ARQ_RPT_RECEIVED == False: + for n in range(0,static.ARQ_TX_N_FRAMES_PER_BURST): #---------------------------BUILD ARQ BURST --------------------------------------------------------------------- - frame_type = 10 + n + 1 #static.ARQ_TX_N_FRAMES_PER_BURST - frame_type = bytes([frame_type]) + frame_type = 10 + n + 1 #static.ARQ_TX_N_FRAMES_PER_BURST + frame_type = bytes([frame_type]) + + payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + n]) - payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + n]) + n_current_arq_frame = static.ARQ_N_SENT_FRAMES + n + 1 + static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes(2, byteorder='big') - n_current_arq_frame = static.ARQ_N_SENT_FRAMES + n + 1 - static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes(2, byteorder='big') - - n_total_arq_frame = len(static.TX_BUFFER) - static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame.to_bytes(2, byteorder='big') - - - - # 1 # frame type and current number of arq frame of burst - # 1 # total number of arq frames per (current) burst - # 2 # current arq frame number - # 2 # total number arq frames - # 2 # arq crc - # N # payload data + n_total_arq_frame = len(static.TX_BUFFER) + static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame.to_bytes(2, byteorder='big') - - arqframe = frame_type + \ + arqframe = frame_type + \ bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ static.ARQ_TX_N_CURRENT_ARQ_FRAME + \ static.ARQ_TX_N_TOTAL_ARQ_FRAMES + \ - static.MYCALLSIGN_CRC8 + \ static.DXCALLSIGN_CRC8 + \ + static.MYCALLSIGN_CRC8 + \ payload_data - #print(arqframe) + #print(arqframe) - buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer - buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send + buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer + buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send - crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 - crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string - buffer += crc # append crc16 to buffer + crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 + crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string + buffer += crc # append crc16 to buffer - data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) - self.c_lib.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer - txbuffer += bytes(mod_out) - txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ + data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) + self.c_lib.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer + txbuffer += bytes(mod_out) + txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ - # -------------- transmit audio + elif static.ARQ_RPT_RECEIVED == True: + for n in range(0,len(static.ARQ_RPT_FRAMES)): + + + missing_frame = int.from_bytes(static.ARQ_RPT_FRAMES[n], "big") + print("MISSING_FRAME: " + str(missing_frame)) + #---------------------------BUILD ARQ BURST --------------------------------------------------------------------- + frame_type = 10 + missing_frame #static.ARQ_TX_N_FRAMES_PER_BURST + frame_type = bytes([frame_type]) + + payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + missing_frame]) + + n_current_arq_frame = static.ARQ_N_SENT_FRAMES + missing_frame + 1 + static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes(2, byteorder='big') + + n_total_arq_frame = len(static.TX_BUFFER) + static.ARQ_TX_N_TOTAL_ARQ_FRAMES = n_total_arq_frame.to_bytes(2, byteorder='big') + + arqframe = frame_type + \ + bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ + static.ARQ_TX_N_CURRENT_ARQ_FRAME + \ + static.ARQ_TX_N_TOTAL_ARQ_FRAMES + \ + static.DXCALLSIGN_CRC8 + \ + static.MYCALLSIGN_CRC8 + \ + payload_data + + #print(arqframe) + + buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer + buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send + + crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), static.FREEDV_DATA_PAYLOAD_PER_FRAME)) # generate CRC16 + crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string + buffer += crc # append crc16 to buffer + + data = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME).from_buffer_copy(buffer) + self.c_lib.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer + txbuffer += bytes(mod_out) + txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ + + + + + + + + + # -------------- transmit audio self.stream_tx.write(bytes(txbuffer)) static.ARQ_STATE = 'RECEIVING_ACK' @@ -299,9 +338,12 @@ class RF(): frametype = int.from_bytes(bytes(data_bytes_out[:1]), "big") frame = frametype - 10 n_frames_per_burst = int.from_bytes(bytes(data_bytes_out[1:2]), "big") - if 50 >= frametype >= 10 and len(data_bytes_out) > 30: # --> The length check filters out random strings without CRC - arq.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16 - + + if 50 >= frametype >= 10: + if frame != 3: + arq.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16 + else: + print("---------------------------3er FRAME") else: print("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out))) @@ -310,9 +352,6 @@ class RF(): if frame == n_frames_per_burst: self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC - # DETECT STUCK IN SYNC - # count rx status 10 - # if 10 greater 2 after 6 then unsync while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_ACK': time.sleep(0.01) @@ -327,15 +366,25 @@ class RF(): nbytes = self.c_lib.freedv_rawdatarx(freedv_signalling, signalling_bytes_out, data_in) # demodulate audio # CHECK IF FRAME CONTAINS ACK------------------------ - frametype = int.from_bytes(bytes(signalling_bytes_out[:1]), "big") - # BURST ACK - if frametype == 60 and nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME: + if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME: + + frametype = int.from_bytes(bytes(signalling_bytes_out[:1]), "big") + + # BURST ACK + if frametype == 60: arq.burst_ack_received() - # FRAME ACK - if frametype == 61 and nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME: + + # FRAME ACK + if frametype == 61: arq.frame_ack_received() + # FRAME RPT + if frametype == 62: + arq.burst_rpt_received(signalling_bytes_out[:-2]) + + + rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) #print(rxstatus) diff --git a/static.py b/static.py index 176c01e7..eff6a162 100644 --- a/static.py +++ b/static.py @@ -87,6 +87,12 @@ ARQ_FRAME_ACK_RECEIVED = 0 # set to 1 if FRAME ACK received ARQ_ACK_TIMEOUT = 0 # set to 1 if timeut reached ARQ_ACK_TIMEOUT_SECONDS = 4.0 #timeout for waiting for ACK frames +ARQ_RX_TIMEOUT = 0 +ARQ_RX_TIMEOUT_SECONDS = 10.0 #timeout for waiting for a frame before resetting RX machine + +ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received +ARQ_RPT_FRAMES = [] + FRAME_CRC = b'' FRAME_BOF = b'\xAA\xAA' #here we define 2 bytes for the BOF FRAME_EOF = b'\xFF\xFF' #here we define 2 bytes for the EOF From 6adf7db48379c1f62195ee4516109f90cfd9f9dd Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 8 Feb 2021 21:25:22 +0100 Subject: [PATCH 03/14] bleeding edge ARQ RPT no working, but with tooo much debugging output furthermore the frame ACK is not working correctly on the TX side --- arq.py | 83 ++++++++++++++++++++++++++++--------------------------- modem.py | 20 +++++++++----- static.py | 5 ++-- 3 files changed, 58 insertions(+), 50 deletions(-) diff --git a/arq.py b/arq.py index 621601d8..f9747a6f 100644 --- a/arq.py +++ b/arq.py @@ -25,13 +25,10 @@ static.ARQ_ACK_PAYLOAD_PER_FRAME = 14 - 2# def arq_ack_timeout(): static.ARQ_ACK_TIMEOUT = 1 +def arq_rpt_timeout(): + static.ARQ_RPT_TIMEOUT = True def data_received(data_in): - - static.ARQ_RX_TIMEOUT = time.time() + static.ARQ_RX_TIMEOUT_SECONDS - while time.time() < static.ARQ_RX_TIMEOUT: - - # arqframe = frame_type + \ # 1 [:1] # frame type and current number of arq frame of (current) burst @@ -80,8 +77,13 @@ def data_received(data_in): #allocate ARQ_RX_BURST_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a burst to N list position so we can explicit search for it + print(len(static.ARQ_RX_BURST_BUFFER)) + print(static.ARQ_N_FRAME) + + if static.ARQ_N_RX_FRAMES_PER_BURSTS != len(static.ARQ_RX_BURST_BUFFER) and static.ARQ_N_FRAME == 1 and frame_type != 51: static.ARQ_RX_BURST_BUFFER = [] + print("ITERATOR!!!!!!!!!!!!!!") for i in range(0,static.ARQ_N_RX_FRAMES_PER_BURSTS+1): static.ARQ_RX_BURST_BUFFER.insert(i,None) @@ -90,12 +92,17 @@ def data_received(data_in): static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) - -# -------------------------- ARQ BURST CHECKER + for i in range(len(static.ARQ_RX_BURST_BUFFER)): + print(static.ARQ_RX_BURST_BUFFER[i]) + + + + +# - ------------------------- ARQ BURST CHECKER # run only if we recieved all ARQ FRAMES per ARQ BURST - if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) == 1: #if received bursts are equal to burst number in frame - + #if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) == 1: #if received bursts are equal to burst number in frame + if static.ARQ_RX_BURST_BUFFER.count(None) == 1: #count nones logging.info("ARQ | TX | BURST ACK") #BUILDING ACK FRAME FOR BURST ----------------------------------------------- @@ -152,8 +159,9 @@ def data_received(data_in): # --------------- IF LIST NOT CONTAINS "None" stick everything together complete_data_frame = bytearray() + print("static.ARQ_RX_FRAME_BUFFER.count(None)" + str(static.ARQ_RX_FRAME_BUFFER.count(None))) if static.ARQ_RX_FRAME_BUFFER.count(None) == 1: ## 1 because position 0 of list will alaways be None in our case - + print("DECODING FRAME!") for frame in range(1,len(static.ARQ_RX_FRAME_BUFFER)): raw_arq_frame = static.ARQ_RX_FRAME_BUFFER[frame] arq_frame_payload = raw_arq_frame[8:] @@ -213,14 +221,15 @@ def data_received(data_in): else: logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") - break + #break def burst_ack_received(): logging.info("ARQ | RX | BURST ACK RCVD!") static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting static.ARQ_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame - + static.RPT_ACK_RECEIVED = False + def burst_rpt_received(data_in): logging.info("ARQ | RX | BURST RPT RCVD!") @@ -311,19 +320,15 @@ def transmit(data_out): logging.debug("ARQ | RX | WAITING FOR BURST ACK") static.ARQ_STATE = 'RECEIVING_ACK' - - + timer = threading.Timer(static.ARQ_ACK_TIMEOUT_SECONDS, arq_ack_timeout) timer.start() - # --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_RPT_RECEIVED == False and static.ARQ_ACK_RECEIVED == 0: time.sleep(0.01) # lets reduce CPU load a little bit #print(static.ARQ_STATE) - - - + #-------------------------------------------------------------------------------------------------------------- if static.ARQ_RPT_RECEIVED == True: @@ -332,41 +337,39 @@ def transmit(data_out): TRANSMIT_ARQ_BURST_THREAD.start() # lets wait during sending. After sending is finished we will continue while static.ARQ_STATE == 'SENDING_DATA': - time.sleep(0.05) - - # --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1 - #reset timer and ack state + time.sleep(0.05) + static.ARQ_FRAME_ACK_RECEIVED = 0 static.ARQ_ACK_RECEIVED = 0 static.ARQ_ACK_TIMEOUT = 0 - logging.debug("ARQ | RX | WAITING FOR BURST ACK") static.ARQ_STATE = 'RECEIVING_ACK' - timer = threading.Timer(static.ARQ_ACK_TIMEOUT_SECONDS, arq_ack_timeout) + timer = threading.Timer(static.ARQ_RPT_TIMEOUT_SECONDS, arq_rpt_timeout) timer.start() - - while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_RPT_RECEIVED == False and static.ARQ_ACK_RECEIVED == 0: + print("kommen wir hier überhaupt an?") + while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RPT_TIMEOUT == False: time.sleep(0.01) # lets reduce CPU load a little bit - #print(static.ARQ_STATE) + print("waiting for ack while rpt") + if static.ARQ_ACK_RECEIVED == 1: + + print("ACK WHILE RPT") + time.sleep(1) + static.ARQ_ACK_TIMEOUT = 1 + static.ARQ_RPT_RECEIVED = False + static.ARQ_RPT_TIMEOUT == False + + break #-------------------------------------------------------------------------------------------------------------- - - - - - - - - - - if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: + if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1 and static.ARQ_RPT_TIMEOUT == True: #logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN") pass #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED OR FRAME ACK HAS BEEN RECEIVED - if static.ARQ_ACK_RECEIVED == 1: + if static.ARQ_ACK_RECEIVED == 1: + print("der interator increment ist wichtig!") #-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break @@ -402,6 +405,6 @@ def transmit(data_out): # BURST MACHINE TO DEFINE N BURSTS PER FRAME ---> LATER WE CAN USE CHANNEL MESSUREMENT TO SET FRAMES PER BURST def get_n_frames_per_burst(): - n_frames_per_burst = randrange(1,10) - #n_frames_per_burst = 1 + #n_frames_per_burst = randrange(1,10) + n_frames_per_burst = 4 return n_frames_per_burst diff --git a/modem.py b/modem.py index f0ca142a..f1106f5f 100644 --- a/modem.py +++ b/modem.py @@ -143,6 +143,7 @@ class RF(): # GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT def transmit_arq_burst(self): static.ARQ_STATE = 'SENDING_DATA' + time.sleep(3) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) freedv = self.c_lib.freedv_open(static.FREEDV_DATA_MODE) @@ -209,9 +210,9 @@ class RF(): frame_type = 10 + missing_frame #static.ARQ_TX_N_FRAMES_PER_BURST frame_type = bytes([frame_type]) - payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + missing_frame]) + payload_data = bytes(static.TX_BUFFER[static.ARQ_N_SENT_FRAMES + missing_frame - 1]) - n_current_arq_frame = static.ARQ_N_SENT_FRAMES + missing_frame + 1 + n_current_arq_frame = static.ARQ_N_SENT_FRAMES + missing_frame static.ARQ_TX_N_CURRENT_ARQ_FRAME = n_current_arq_frame.to_bytes(2, byteorder='big') n_total_arq_frame = len(static.TX_BUFFER) @@ -253,7 +254,8 @@ class RF(): #-------------------------------------------------------------------------------------------------------- def receive(self,data_mode,signalling_mode): - + force = False + self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) freedv_data = self.c_lib.freedv_open(data_mode) @@ -294,7 +296,7 @@ class RF(): 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 - #print(self.c_lib.freedv_get_rx_status(freedv_data)) + print(self.c_lib.freedv_get_rx_status(freedv_data)) #-------------STUCK IN SYNC DETECTOR @@ -340,10 +342,11 @@ class RF(): n_frames_per_burst = int.from_bytes(bytes(data_bytes_out[1:2]), "big") if 50 >= frametype >= 10: - if frame != 3: + if frame != 3 or force == True: arq.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16 else: print("---------------------------3er FRAME") + force = True else: print("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out))) @@ -352,7 +355,10 @@ class RF(): if frame == n_frames_per_burst: self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC - + if static.ARQ_RX_BURST_BUFFER.count(None) == 1: + self.c_lib.freedv_set_sync(freedv_data, 0) + + while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_ACK': time.sleep(0.01) @@ -387,7 +393,7 @@ class RF(): rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) - #print(rxstatus) + print(rxstatus) if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10: self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC diff --git a/static.py b/static.py index eff6a162..0da64763 100644 --- a/static.py +++ b/static.py @@ -87,9 +87,8 @@ ARQ_FRAME_ACK_RECEIVED = 0 # set to 1 if FRAME ACK received ARQ_ACK_TIMEOUT = 0 # set to 1 if timeut reached ARQ_ACK_TIMEOUT_SECONDS = 4.0 #timeout for waiting for ACK frames -ARQ_RX_TIMEOUT = 0 -ARQ_RX_TIMEOUT_SECONDS = 10.0 #timeout for waiting for a frame before resetting RX machine - +ARQ_RPT_TIMEOUT = False +ARQ_RPT_TIMEOUT_SECONDS = 4.0 ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received ARQ_RPT_FRAMES = [] From 0a8ea24112b868c48328c8478b16741ee9f2f9e1 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Tue, 9 Feb 2021 12:35:24 +0100 Subject: [PATCH 04/14] improved RPT Now working, but still timing issues and stuck in sync --- arq.py | 153 ++++++++++++++++++++++++------------------------------ modem.py | 126 ++++++++++++-------------------------------- static.py | 4 +- 3 files changed, 103 insertions(+), 180 deletions(-) diff --git a/arq.py b/arq.py index f9747a6f..26f184eb 100644 --- a/arq.py +++ b/arq.py @@ -39,13 +39,8 @@ def data_received(data_in): # payload_data # N [8:N] # payload data - # detect if we got a RPT frame - if int.from_bytes(bytes(data_in[:1]), "big") == 51: - frame_type = int.from_bytes(bytes(data_in[:1]), "big") - else: - frame_type = 10 - static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame - + + static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame static.ARQ_N_RX_FRAMES_PER_BURSTS = int.from_bytes(bytes(data_in[1:2]), "big") #get number of bursts from received frame static.ARQ_RX_N_CURRENT_ARQ_FRAME = int.from_bytes(bytes(data_in[2:4]), "big") #get current number of total frames static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = int.from_bytes(bytes(data_in[4:6]), "big") # get get total number of frames @@ -70,33 +65,32 @@ def data_received(data_in): #allocate ARQ_RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a data frame to N list position so we can explicit search for it - if static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME != len(static.ARQ_RX_FRAME_BUFFER) and static.ARQ_RX_N_CURRENT_ARQ_FRAME == 1: + + try: + static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) + + except IndexError: + static.ARQ_RX_FRAME_BUFFER = [] for i in range(0,static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME+1): static.ARQ_RX_FRAME_BUFFER.insert(i,None) + + static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) + + + try: + static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) - #allocate ARQ_RX_BURST_BUFFER as a list with "None" if not already done. This should be done only once per burst! - # here we will save the N frame of a burst to N list position so we can explicit search for it - print(len(static.ARQ_RX_BURST_BUFFER)) - print(static.ARQ_N_FRAME) - - - if static.ARQ_N_RX_FRAMES_PER_BURSTS != len(static.ARQ_RX_BURST_BUFFER) and static.ARQ_N_FRAME == 1 and frame_type != 51: + except IndexError: + static.ARQ_RX_BURST_BUFFER = [] - print("ITERATOR!!!!!!!!!!!!!!") for i in range(0,static.ARQ_N_RX_FRAMES_PER_BURSTS+1): static.ARQ_RX_BURST_BUFFER.insert(i,None) - - - # now we add the incoming data to the specified position in our lists - static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) - static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) - - for i in range(len(static.ARQ_RX_BURST_BUFFER)): - print(static.ARQ_RX_BURST_BUFFER[i]) - - - + + static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) + + #for i in range(len(static.ARQ_RX_BURST_BUFFER)): + # print(static.ARQ_RX_BURST_BUFFER[i]) # - ------------------------- ARQ BURST CHECKER @@ -108,60 +102,43 @@ def data_received(data_in): #BUILDING ACK FRAME FOR BURST ----------------------------------------------- ack_payload = b'ACK FRAME' ack_frame = b'<' + ack_payload # < = 60 - ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) - ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send - + #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- - modem.transmit_arq_ack(ack_buffer) + modem.transmit_arq_ack(ack_frame) #clear burst buffer static.ARQ_RX_BURST_BUFFER = [] #if decoded N frames are unequal to expected frames per burst elif static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) != 1: - print("RPT FRAME NEEDS TO BE SEND!!!!") + # --------------- CHECK WHICH BURST FRAMES WE ARE MISSING ------------------------------------------- missing_frames = b'' for burst in range(1,len(static.ARQ_RX_BURST_BUFFER)): if static.ARQ_RX_BURST_BUFFER[burst] == None: - print(burst) burst = burst.to_bytes(2, byteorder='big') missing_frames += burst - - - print("MISSING FRAMES: " + str(missing_frames)) + + logging.info("ARQ | TX | RPT ARQ FRAMES [" + str(missing_frames) + "]") + #BUILDING RPT FRAME FOR BURST ----------------------------------------------- rpt_payload = missing_frames rpt_frame = b'>' + rpt_payload #> = 63 - rpt_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) - rpt_buffer[:len(rpt_frame)] = rpt_frame # set buffersize to length of data which will be send - modem.transmit_arq_ack(rpt_buffer) - - - - - - - - - + #TRANSMIT RPT FRAME FOR BURST----------------------------------------------- + modem.transmit_arq_ack(rpt_frame) + # ---------------------------- FRAME MACHINE - - # --------------- CHECK IF WE ARE MISSING FRAMES ------------------------------------------- - #for frame in range(1,len(static.ARQ_RX_FRAME_BUFFER)): - # if static.ARQ_RX_FRAME_BUFFER[frame] == None: - # print("Missing frames:" + str(frame)) - + # --------------- IF LIST NOT CONTAINS "None" stick everything together complete_data_frame = bytearray() - print("static.ARQ_RX_FRAME_BUFFER.count(None)" + str(static.ARQ_RX_FRAME_BUFFER.count(None))) + #print("static.ARQ_RX_FRAME_BUFFER.count(None)" + str(static.ARQ_RX_FRAME_BUFFER.count(None))) if static.ARQ_RX_FRAME_BUFFER.count(None) == 1: ## 1 because position 0 of list will alaways be None in our case - print("DECODING FRAME!") + #print("DECODING FRAME!") for frame in range(1,len(static.ARQ_RX_FRAME_BUFFER)): raw_arq_frame = static.ARQ_RX_FRAME_BUFFER[frame] arq_frame_payload = raw_arq_frame[8:] @@ -199,13 +176,12 @@ def data_received(data_in): #BUILDING ACK FRAME FOR DATA FRAME ----------------------------------------------- - ack_frame = b'='+ bytes(static.FRAME_CRC) # < = 61 - ack_buffer = bytearray(static.ARQ_ACK_PAYLOAD_PER_FRAME) - ack_buffer[:len(ack_frame)] = ack_frame # set buffersize to length of data which will be send + ack_frame = b'='+ bytes(static.FRAME_CRC) # < = 61 #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- logging.info("ARQ | TX | ARQ DATA FRAME ACK [" + str(static.FRAME_CRC.hex()) +"]") - modem.transmit_arq_ack(ack_buffer) + time.sleep(0.5) + modem.transmit_arq_ack(ack_frame) # clearing buffers and resetting counters static.ARQ_RX_BURST_BUFFER = [] @@ -220,28 +196,34 @@ def data_received(data_in): else: logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") - - #break + def burst_ack_received(): logging.info("ARQ | RX | BURST ACK RCVD!") static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting static.ARQ_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame - static.RPT_ACK_RECEIVED = False + + static.ARQ_RPT_TIMEOUT = True #Force timer to stop waiting + static.ARQ_RPT_RECEIVED = False + static.ARQ_RPT_FRAMES = [] def burst_rpt_received(data_in): logging.info("ARQ | RX | BURST RPT RCVD!") static.ARQ_ACK_TIMEOUT = 0 #Force timer to stop waiting static.ARQ_ACK_RECEIVED = 0 #Force data loops of TNC to stop and continue with next frame + static.ARQ_RPT_RECEIVED = True - #static.ARQ_RPT_FRAMES = b'123' - missing = 3 - missing = missing.to_bytes(2, byteorder='big') - static.ARQ_RPT_FRAMES.insert(0,missing) + static.ARQ_RPT_FRAMES = [] - print(bytes(data_in)) + missing_area = bytes(data_in[1:9]) + + for i in range(0,6,2): + if not missing_area[i:i+2].endswith(b'\x00\x00'): + missing = missing_area[i:i+2] + static.ARQ_RPT_FRAMES.insert(0,missing) + def frame_ack_received(): @@ -249,7 +231,8 @@ def frame_ack_received(): logging.info("ARQ | RX | FRAME ACK RCVD!") static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting static.ARQ_FRAME_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame - + static.RPT_ACK_RECEIVED = False + static.ARQ_RPT_TIMEOUT = True def transmit(data_out): @@ -310,6 +293,7 @@ def transmit(data_out): # lets wait during sending. After sending is finished we will continue while static.ARQ_STATE == 'SENDING_DATA': time.sleep(0.05) + print("sending.....") # --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1 @@ -325,14 +309,14 @@ def transmit(data_out): timer.start() # --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN - while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_RPT_RECEIVED == False and static.ARQ_ACK_RECEIVED == 0: + while (static.ARQ_ACK_RECEIVED == 0 or static.ARQ_RPT_RECEIVED == False or static.ARQ_FRAME_ACK_RECEIVED == 0) and static.ARQ_TIMEOUT_RECEIVED == 0: time.sleep(0.01) # lets reduce CPU load a little bit #print(static.ARQ_STATE) #-------------------------------------------------------------------------------------------------------------- if static.ARQ_RPT_RECEIVED == True: - print("lets send a rpt packet") + TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") TRANSMIT_ARQ_BURST_THREAD.start() # lets wait during sending. After sending is finished we will continue @@ -342,34 +326,32 @@ def transmit(data_out): static.ARQ_FRAME_ACK_RECEIVED = 0 static.ARQ_ACK_RECEIVED = 0 static.ARQ_ACK_TIMEOUT = 0 + static.ARQ_RPT_TIMEOUT = False static.ARQ_STATE = 'RECEIVING_ACK' timer = threading.Timer(static.ARQ_RPT_TIMEOUT_SECONDS, arq_rpt_timeout) timer.start() - print("kommen wir hier überhaupt an?") - while static.ARQ_ACK_TIMEOUT == 0 and static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RPT_TIMEOUT == False: + + while static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RPT_TIMEOUT == False: time.sleep(0.01) # lets reduce CPU load a little bit - print("waiting for ack while rpt") + if static.ARQ_ACK_RECEIVED == 1: print("ACK WHILE RPT") - time.sleep(1) - static.ARQ_ACK_TIMEOUT = 1 - static.ARQ_RPT_RECEIVED = False - static.ARQ_RPT_TIMEOUT == False - break + static.ARQ_ACK_TIMEOUT = 1 + static.ARQ_RPT_TIMEOUT = True + #break #-------------------------------------------------------------------------------------------------------------- - if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1 and static.ARQ_RPT_TIMEOUT == True: - #logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN") - pass + #if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: + # #logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN") + # pass - #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED OR FRAME ACK HAS BEEN RECEIVED - if static.ARQ_ACK_RECEIVED == 1: - print("der interator increment ist wichtig!") + #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED + if static.ARQ_ACK_RECEIVED == 1: #-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break @@ -384,7 +366,6 @@ def transmit(data_out): # ----------- if no ACK received and out of retries.....stop frame sending if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_FRAME_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: logging.info("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") - break #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK diff --git a/modem.py b/modem.py index f1106f5f..2751f5b7 100644 --- a/modem.py +++ b/modem.py @@ -56,53 +56,10 @@ class RF(): #--------------------------------------------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() -#-------------------------------------------------------------------------------------------------------- - # GET DATA AND MODULATE IT - - def transmit(self,mode,data_out): - 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) - payload_per_frame = bytes_per_frame -2 - n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples(freedv) - n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples(freedv)*2 #get n_tx_modem_samples which defines the size of the modulation object - - mod_out = ctypes.c_short * n_tx_modem_samples - mod_out = mod_out() - mod_out_preamble = ctypes.c_short * n_tx_modem_samples #1760 for mode 10,11,12 #4000 for mode 9 - mod_out_preamble = mod_out_preamble() - - data_list = [data_out[i:i+payload_per_frame] for i in range(0, len(data_out), payload_per_frame)] # split incomming bytes to size of 30bytes, create a list and loop through it - data_list_length = len(data_list) - for i in range(data_list_length): # LOOP THROUGH DATA LIST - - buffer = bytearray(payload_per_frame) # use this if CRC16 checksum is required ( DATA1-3) - buffer[:len(data_list[i])] = data_list[i] # set buffersize to length of data which will be send - - crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), payload_per_frame)) # generate CRC16 - crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string - buffer += crc # append crc16 to buffer - - data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer) - self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble) - self.c_lib.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and safe it into mod_out pointer - - # -------------- preamble area - # WE NEED TO ADJUST IT FOR SINGLE TRANSMISSION - - txbuffer = bytearray() - txbuffer += bytes(mod_out_preamble) - txbuffer += bytes(mod_out) - txbuffer = txbuffer.rstrip(b'\x00') - - - # -------------- transmit audio - self.stream_tx.write(bytes(txbuffer)) - #-------------------------------------------------------------------------------------------------------- def transmit_arq_ack(self,ack_buffer): - + #print(ack_buffer) static.ARQ_STATE = 'SENDING_ACK' self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) @@ -123,7 +80,6 @@ class RF(): crc = ctypes.c_ushort(self.c_lib.freedv_gen_crc16(bytes(buffer), payload_per_frame)) # generate CRC16 crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string buffer += crc # append crc16 to buffer - #print(bytes(buffer)) data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer) preamble_bytes = self.c_lib.freedv_rawdatapreambletx(freedv, mod_out_preamble) @@ -137,14 +93,13 @@ class RF(): # -------------- transmit audio twice self.stream_tx.write(bytes(txbuffer)) self.stream_tx.write(bytes(txbuffer)) - + static.ARQ_STATE = 'RECEIVING_DATA' #-------------------------------------------------------------------------------------------------------- # GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT def transmit_arq_burst(self): static.ARQ_STATE = 'SENDING_DATA' - time.sleep(3) - + self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) freedv = self.c_lib.freedv_open(static.FREEDV_DATA_MODE) static.FREEDV_DATA_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv)/8) @@ -202,10 +157,9 @@ class RF(): elif static.ARQ_RPT_RECEIVED == True: for n in range(0,len(static.ARQ_RPT_FRAMES)): - - + missing_frame = int.from_bytes(static.ARQ_RPT_FRAMES[n], "big") - print("MISSING_FRAME: " + str(missing_frame)) + print("MISSING ARQ FRAME: " + str(missing_frame)) #---------------------------BUILD ARQ BURST --------------------------------------------------------------------- frame_type = 10 + missing_frame #static.ARQ_TX_N_FRAMES_PER_BURST frame_type = bytes([frame_type]) @@ -225,9 +179,7 @@ class RF(): static.DXCALLSIGN_CRC8 + \ static.MYCALLSIGN_CRC8 + \ payload_data - - #print(arqframe) - + buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send @@ -240,13 +192,7 @@ class RF(): txbuffer += bytes(mod_out) txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ - - - - - - - + # -------------- transmit audio self.stream_tx.write(bytes(txbuffer)) @@ -280,9 +226,7 @@ class RF(): stuck_in_sync_counter = 0 stuck_in_sync_10_counter = 0 # - - - + while static.ARQ_STATE == 'RECEIVING_DATA': time.sleep(0.01) @@ -296,7 +240,7 @@ class RF(): 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 - print(self.c_lib.freedv_get_rx_status(freedv_data)) + #print(self.c_lib.freedv_get_rx_status(freedv_data)) #-------------STUCK IN SYNC DETECTOR @@ -306,12 +250,12 @@ class RF(): #print(stuck_in_sync_counter) - if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv_data) == 10: - print("stuck in sync #1 --> DOING UNSYNC") - self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC - stuck_in_sync_counter = 0 - stuck_in_sync_10_counter = 0 - data_in = None + #if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv_data) == 10: + # print("stuck in sync #1 --> DOING UNSYNC") + # self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC + # stuck_in_sync_counter = 0 + # stuck_in_sync_10_counter = 0 + # data_in = None if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2: @@ -321,16 +265,10 @@ class RF(): stuck_in_sync_10_counter = 0 data_in = None #----------------------------------- - - - #modem_stats_snr = c_float() - #modem_stats_sync = c_int() - - #self.c_lib.freedv_get_modem_stats(freedv_data,byref(modem_stats_sync), byref(modem_stats_snr)) - #modem_stats_snr = modem_stats_snr.value - #print(modem_stats_snr) + if nbytes == static.FREEDV_DATA_BYTES_PER_FRAME: + # counter reset for stuck in sync counter stuck_in_sync_counter = 0 stuck_in_sync_10_counter = 0 @@ -344,20 +282,24 @@ class RF(): if 50 >= frametype >= 10: if frame != 3 or force == True: arq.data_received(bytes(data_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: + print("FULL BURST BUFFER ---> UNSYNC") + self.c_lib.freedv_set_sync(freedv_data, 0) + else: - print("---------------------------3er FRAME") + print("---------------------------SIMULATED MISSING FRAME") force = True else: print("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out))) - # NEEDS TO BE OPTIMIZED - # DO UNSYNC AFTER LAST BURST by checking the frame numbers agains the total frames per burst + + # DO UNSYNC AFTER LAST BURST by checking the frame numbers agains the total frames per burst if frame == n_frames_per_burst: + print("LAST FRAME ---> UNSYNC") self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC - - if static.ARQ_RX_BURST_BUFFER.count(None) == 1: - self.c_lib.freedv_set_sync(freedv_data, 0) + while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_ACK': time.sleep(0.01) @@ -374,8 +316,9 @@ class RF(): # 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") + print("SIGNALLING RECEIVED") # BURST ACK if frametype == 60: @@ -384,16 +327,15 @@ class RF(): # FRAME ACK if frametype == 61: arq.frame_ack_received() - + # FRAME RPT if frametype == 62: arq.burst_rpt_received(signalling_bytes_out[:-2]) - - - + rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) + print("ACK") print(rxstatus) - if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10: - self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC + #if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME:# or rxstatus == 10: + # self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC diff --git a/static.py b/static.py index 0da64763..0222509a 100644 --- a/static.py +++ b/static.py @@ -85,10 +85,10 @@ ARQ_ACK_PAYLOAD_PER_FRAME = 0 # PAYLOAD per ACK frame ARQ_ACK_RECEIVED = 0 # set to 1 if ACK received ARQ_FRAME_ACK_RECEIVED = 0 # set to 1 if FRAME ACK received ARQ_ACK_TIMEOUT = 0 # set to 1 if timeut reached -ARQ_ACK_TIMEOUT_SECONDS = 4.0 #timeout for waiting for ACK frames +ARQ_ACK_TIMEOUT_SECONDS = 6.0 #timeout for waiting for ACK frames ARQ_RPT_TIMEOUT = False -ARQ_RPT_TIMEOUT_SECONDS = 4.0 +ARQ_RPT_TIMEOUT_SECONDS = 6.0 ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received ARQ_RPT_FRAMES = [] From 91114d0db2acdab884979f183bedb7aeb0168443 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Tue, 9 Feb 2021 14:27:36 +0100 Subject: [PATCH 05/14] improved state and timing --- arq.py | 182 ++++++++++++++++++++++++++++++----------------------- helpers.py | 12 +++- modem.py | 16 ++--- static.py | 17 ++--- 4 files changed, 133 insertions(+), 94 deletions(-) diff --git a/arq.py b/arq.py index 26f184eb..193eb702 100644 --- a/arq.py +++ b/arq.py @@ -22,11 +22,11 @@ modem = modem.RF() static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 3 #6?! static.ARQ_ACK_PAYLOAD_PER_FRAME = 14 - 2# -def arq_ack_timeout(): - static.ARQ_ACK_TIMEOUT = 1 +#def arq_ack_timeout(): +# static.ARQ_ACK_TIMEOUT = 1 -def arq_rpt_timeout(): - static.ARQ_RPT_TIMEOUT = True +#def arq_rpt_timeout(): +# static.ARQ_RPT_TIMEOUT = True def data_received(data_in): @@ -75,7 +75,9 @@ def data_received(data_in): for i in range(0,static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME+1): static.ARQ_RX_FRAME_BUFFER.insert(i,None) - static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) + static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) + static.ARQ_FRAME_BOF_RECEIVED = False + static.ARQ_FRAME_EOF_RECEIVED = False try: @@ -95,7 +97,6 @@ def data_received(data_in): # - ------------------------- ARQ BURST CHECKER # run only if we recieved all ARQ FRAMES per ARQ BURST - #if static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) == 1: #if received bursts are equal to burst number in frame if static.ARQ_RX_BURST_BUFFER.count(None) == 1: #count nones logging.info("ARQ | TX | BURST ACK") @@ -115,11 +116,11 @@ def data_received(data_in): # --------------- CHECK WHICH BURST FRAMES WE ARE MISSING ------------------------------------------- missing_frames = b'' - for burst in range(1,len(static.ARQ_RX_BURST_BUFFER)): + for burstnumber in range(1,len(static.ARQ_RX_BURST_BUFFER)): - if static.ARQ_RX_BURST_BUFFER[burst] == None: - burst = burst.to_bytes(2, byteorder='big') - missing_frames += burst + if static.ARQ_RX_BURST_BUFFER[burstnumber] == None: + frame_number = burstnumber.to_bytes(2, byteorder='big') + missing_frames += frame_number logging.info("ARQ | TX | RPT ARQ FRAMES [" + str(missing_frames) + "]") @@ -179,8 +180,9 @@ def data_received(data_in): ack_frame = b'='+ bytes(static.FRAME_CRC) # < = 61 #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- + time.sleep(0.5) #0.5 logging.info("ARQ | TX | ARQ DATA FRAME ACK [" + str(static.FRAME_CRC.hex()) +"]") - time.sleep(0.5) + modem.transmit_arq_ack(ack_frame) # clearing buffers and resetting counters @@ -196,43 +198,10 @@ def data_received(data_in): else: logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") - - -def burst_ack_received(): - - logging.info("ARQ | RX | BURST ACK RCVD!") - static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting - static.ARQ_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame - - static.ARQ_RPT_TIMEOUT = True #Force timer to stop waiting - static.ARQ_RPT_RECEIVED = False - static.ARQ_RPT_FRAMES = [] - -def burst_rpt_received(data_in): - - logging.info("ARQ | RX | BURST RPT RCVD!") - static.ARQ_ACK_TIMEOUT = 0 #Force timer to stop waiting - static.ARQ_ACK_RECEIVED = 0 #Force data loops of TNC to stop and continue with next frame - - static.ARQ_RPT_RECEIVED = True - static.ARQ_RPT_FRAMES = [] - - missing_area = bytes(data_in[1:9]) - - for i in range(0,6,2): - if not missing_area[i:i+2].endswith(b'\x00\x00'): - missing = missing_area[i:i+2] - static.ARQ_RPT_FRAMES.insert(0,missing) + -def frame_ack_received(): - - logging.info("ARQ | RX | FRAME ACK RCVD!") - static.ARQ_ACK_TIMEOUT = 1 #Force timer to stop waiting - static.ARQ_FRAME_ACK_RECEIVED = 1 #Force data loops of TNC to stop and continue with next frame - static.RPT_ACK_RECEIVED = False - static.ARQ_RPT_TIMEOUT = True def transmit(data_out): @@ -282,7 +251,7 @@ def transmit(data_out): #--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK RECEPTION FAILS 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.info("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) + "]") @@ -292,84 +261,93 @@ def transmit(data_out): # lets wait during sending. After sending is finished we will continue while static.ARQ_STATE == 'SENDING_DATA': - time.sleep(0.05) - print("sending.....") - + time.sleep(0.01) + #print("sending.....") + # --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1 #reset timer and ack state - static.ARQ_FRAME_ACK_RECEIVED = 0 - static.ARQ_ACK_RECEIVED = 0 - static.ARQ_ACK_TIMEOUT = 0 + static.ARQ_FRAME_ACK_RECEIVED = False + static.ARQ_ACK_RECEIVED = False + static.ARQ_RX_ACK_TIMEOUT = False - logging.debug("ARQ | RX | WAITING FOR BURST ACK") - static.ARQ_STATE = 'RECEIVING_ACK' + logging.info("ARQ | RX | WAITING FOR BURST ACK") + static.ARQ_STATE = 'RECEIVING_SIGNALLING' - timer = threading.Timer(static.ARQ_ACK_TIMEOUT_SECONDS, arq_ack_timeout) + timer = threading.Timer(static.ARQ_RX_ACK_TIMEOUT_SECONDS, helpers.arq_ack_timeout) timer.start() # --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN - while (static.ARQ_ACK_RECEIVED == 0 or static.ARQ_RPT_RECEIVED == False or static.ARQ_FRAME_ACK_RECEIVED == 0) and static.ARQ_TIMEOUT_RECEIVED == 0: + while (static.ARQ_ACK_RECEIVED == False or static.ARQ_RPT_RECEIVED == False or static.ARQ_FRAME_ACK_RECEIVED == False) and static.ARQ_RX_ACK_TIMEOUT == False: time.sleep(0.01) # lets reduce CPU load a little bit #print(static.ARQ_STATE) #-------------------------------------------------------------------------------------------------------------- if static.ARQ_RPT_RECEIVED == True: - + + logging.info("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) + logging.info("ARQ | TX | SENDING REQUESTED FRAMES: " + str(static.ARQ_RPT_FRAMES)) TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") TRANSMIT_ARQ_BURST_THREAD.start() + # lets wait during sending. After sending is finished we will continue while static.ARQ_STATE == 'SENDING_DATA': - time.sleep(0.05) + time.sleep(0.01) - static.ARQ_FRAME_ACK_RECEIVED = 0 - static.ARQ_ACK_RECEIVED = 0 - static.ARQ_ACK_TIMEOUT = 0 - static.ARQ_RPT_TIMEOUT = False + static.ARQ_FRAME_ACK_RECEIVED = False + static.ARQ_ACK_RECEIVED = False + static.ARQ_RX_ACK_TIMEOUT = False + static.ARQ_RX_RPT_TIMEOUT = False - static.ARQ_STATE = 'RECEIVING_ACK' + static.ARQ_STATE = 'RECEIVING_SIGNALLING' - timer = threading.Timer(static.ARQ_RPT_TIMEOUT_SECONDS, arq_rpt_timeout) + timer = threading.Timer(static.ARQ_RX_RPT_TIMEOUT_SECONDS, helpers.arq_rpt_timeout) timer.start() - while static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RPT_TIMEOUT == False: + while static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_RPT_TIMEOUT == False: time.sleep(0.01) # lets reduce CPU load a little bit - if static.ARQ_ACK_RECEIVED == 1: + if static.ARQ_ACK_RECEIVED == True: - print("ACK WHILE RPT") + logging.info("ARQ | RX | ACK RECEIVED AFTER FRAME REPEAT") - static.ARQ_ACK_TIMEOUT = 1 - static.ARQ_RPT_TIMEOUT = True - #break + static.ARQ_RX_ACK_TIMEOUT = True + static.ARQ_RX_RPT_TIMEOUT = True + static.ARQ_RPT_FRAMES = [] + + if static.ARQ_RX_RPT_TIMEOUT == True and static.ARQ_ACK_RECEIVED == False: + print("Burst lost....") + static.ARQ_RPT_RECEIVED = False + static.ARQ_RPT_FRAMES = [] #-------------------------------------------------------------------------------------------------------------- - #if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: + #if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RX_ACK_TIMEOUT == 1: # #logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN") # pass #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED - if static.ARQ_ACK_RECEIVED == 1: + if static.ARQ_ACK_RECEIVED == True: + logging.info("ARQ | RX | ACK RECEIVED") #-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break #--------------- BREAK LOOP IF FRAME ACK HAS BEEN RECEIVED EARLIER AS EXPECTED - if static.ARQ_FRAME_ACK_RECEIVED == 1: + if static.ARQ_FRAME_ACK_RECEIVED == True: logging.info("ARQ | RX | EARLY FRAME ACK RECEIVED - STOPPING TX") #static.ARQ_N_SENT_FRAMES = #static.TX_BUFFER_SIZE static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break # ----------- if no ACK received and out of retries.....stop frame sending - if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_FRAME_ACK_RECEIVED == 0 and static.ARQ_ACK_TIMEOUT == 1: + if static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_ACK_TIMEOUT == True: logging.info("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") break #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK - if static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == 1: + if static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == True: logging.info("ARQ | RX | REGULAR FRAME ACK RECEIVED - DATA TRANSMITTED!") break @@ -379,9 +357,16 @@ def transmit(data_out): logging.info("ARQ | TX | BUFFER EMPTY") # - RESET COUNTERS static.ARQ_N_SENT_FRAMES = 0 - static.ARQ_TX_N_FRAMES_PER_BURST = 0 - static.ARQ_ACK_RECEIVED = 0 - static.ARQ_FRAME_ACK_RECEIVED = 0 + static.ARQ_TX_N_FRAMES_PER_BURST = False + static.ARQ_ACK_RECEIVED = False + static.ARQ_FRAME_ACK_RECEIVED = False + + + + + + + # BURST MACHINE TO DEFINE N BURSTS PER FRAME ---> LATER WE CAN USE CHANNEL MESSUREMENT TO SET FRAMES PER BURST def get_n_frames_per_burst(): @@ -389,3 +374,44 @@ def get_n_frames_per_burst(): #n_frames_per_burst = randrange(1,10) n_frames_per_burst = 4 return n_frames_per_burst + + + +def burst_ack_received(): + + #logging.info("ARQ | RX | BURST ACK RCVD!") + static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting + static.ARQ_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame + + static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting + static.ARQ_RPT_RECEIVED = False + static.ARQ_RPT_FRAMES = [] + + +def frame_ack_received(): + + #logging.info("ARQ | RX | FRAME ACK RCVD!") + static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting + static.ARQ_FRAME_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame + + static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting + static.ARQ_RPT_RECEIVED = False + static.ARQ_RPT_FRAMES = [] + + +def burst_rpt_received(data_in): + + #logging.info("ARQ | RX | BURST RPT RCVD!") + static.ARQ_RX_ACK_TIMEOUT = False #Force timer to stop waiting + static.ARQ_ACK_RECEIVED = False #Force data loops of TNC to stop and continue with next frame + + static.ARQ_RPT_RECEIVED = True + static.ARQ_RPT_FRAMES = [] + + missing_area = bytes(data_in[1:9]) + + for i in range(0,6,2): + if not missing_area[i:i+2].endswith(b'\x00\x00'): + missing = missing_area[i:i+2] + static.ARQ_RPT_FRAMES.insert(0,missing) + diff --git a/helpers.py b/helpers.py index 7f37122e..ba1bc704 100644 --- a/helpers.py +++ b/helpers.py @@ -26,4 +26,14 @@ def get_crc_16(data): crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library crc_data = crc_algorithm(data) crc_data = crc_data.to_bytes(2, byteorder='big') - return crc_data \ No newline at end of file + return crc_data + + +def arq_ack_timeout(): + static.ARQ_RX_ACK_TIMEOUT = True + #print("ARQ_RX_ACK_TIMEOUT") + +def arq_rpt_timeout(): + static.ARQ_RX_RPT_TIMEOUT = True + #print("ARQ_RX_RPT_TIMEOUT") + diff --git a/modem.py b/modem.py index 2751f5b7..24e13540 100644 --- a/modem.py +++ b/modem.py @@ -156,10 +156,11 @@ class RF(): txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ elif static.ARQ_RPT_RECEIVED == True: + for n in range(0,len(static.ARQ_RPT_FRAMES)): missing_frame = int.from_bytes(static.ARQ_RPT_FRAMES[n], "big") - print("MISSING ARQ FRAME: " + str(missing_frame)) + #---------------------------BUILD ARQ BURST --------------------------------------------------------------------- frame_type = 10 + missing_frame #static.ARQ_TX_N_FRAMES_PER_BURST frame_type = bytes([frame_type]) @@ -196,7 +197,8 @@ class RF(): # -------------- transmit audio self.stream_tx.write(bytes(txbuffer)) - static.ARQ_STATE = 'RECEIVING_ACK' + static.ARQ_STATE = 'IDLE' + #static.ARQ_STATE = 'RECEIVING_SIGNALLING' #-------------------------------------------------------------------------------------------------------- def receive(self,data_mode,signalling_mode): @@ -281,7 +283,8 @@ class RF(): if 50 >= frametype >= 10: if frame != 3 or force == True: - arq.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16 + arq.data_received(bytes(data_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: print("FULL BURST BUFFER ---> UNSYNC") @@ -301,7 +304,7 @@ class RF(): - while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_ACK': + while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_SIGNALLING': time.sleep(0.01) nin = self.c_lib.freedv_nin(freedv_signalling) @@ -318,7 +321,6 @@ class RF(): 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") - print("SIGNALLING RECEIVED") # BURST ACK if frametype == 60: @@ -334,8 +336,8 @@ class RF(): rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) - print("ACK") - print(rxstatus) + #print("ACK") + #print(rxstatus) #if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME:# or rxstatus == 10: # self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC diff --git a/static.py b/static.py index 0222509a..b7570668 100644 --- a/static.py +++ b/static.py @@ -82,15 +82,16 @@ ARQ_N_RX_ARQ_FRAMES = 0 # total number of received frames ARQ_N_RX_FRAMES_PER_BURSTS = 0 # NUMBER OF FRAMES WE ARE WAITING FOR --> GOT DATA FROM RECEIVED FRAME ARQ_ACK_PAYLOAD_PER_FRAME = 0 # PAYLOAD per ACK frame -ARQ_ACK_RECEIVED = 0 # set to 1 if ACK received -ARQ_FRAME_ACK_RECEIVED = 0 # set to 1 if FRAME ACK received -ARQ_ACK_TIMEOUT = 0 # set to 1 if timeut reached -ARQ_ACK_TIMEOUT_SECONDS = 6.0 #timeout for waiting for ACK frames -ARQ_RPT_TIMEOUT = False -ARQ_RPT_TIMEOUT_SECONDS = 6.0 +ARQ_ACK_RECEIVED = False # set to 1 if ACK received +ARQ_FRAME_ACK_RECEIVED = False # set to 1 if FRAME ACK received +ARQ_RX_ACK_TIMEOUT = False # set to 1 if timeut reached +ARQ_RX_ACK_TIMEOUT_SECONDS = 6.0 #timeout for waiting for ACK frames + +ARQ_RX_RPT_TIMEOUT = False +ARQ_RX_RPT_TIMEOUT_SECONDS = 6.0 ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received -ARQ_RPT_FRAMES = [] +ARQ_RPT_FRAMES = [] #buffer for frames which are requested to repeat FRAME_CRC = b'' FRAME_BOF = b'\xAA\xAA' #here we define 2 bytes for the BOF @@ -105,7 +106,7 @@ ARQ_N_SENT_FRAMES = 0 #counter for already sent frames # IDLE # RECEIVING_DATA # SENDING_DATA -# RECEIVING_ACK +# RECEIVING_SIGNALLING # SENDING_ACK # ACK_RECEIVED # From cebaf469db51c3feb1f9d3c55a6c5cfcdb638ae3 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Wed, 10 Feb 2021 15:04:18 +0100 Subject: [PATCH 06/14] improved helpers --- helpers.py | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/helpers.py b/helpers.py index ba1bc704..d2b2d1e3 100644 --- a/helpers.py +++ b/helpers.py @@ -30,10 +30,42 @@ def get_crc_16(data): def arq_ack_timeout(): - static.ARQ_RX_ACK_TIMEOUT = True - #print("ARQ_RX_ACK_TIMEOUT") + if static.ARQ_STATE == 'RECEIVING_SIGNALLING': + static.ARQ_RX_ACK_TIMEOUT = True + print("ARQ_RX_ACK_TIMEOUT") + + def arq_rpt_timeout(): - static.ARQ_RX_RPT_TIMEOUT = True - #print("ARQ_RX_RPT_TIMEOUT") + if static.ARQ_STATE == 'RECEIVING_SIGNALLING': + static.ARQ_RX_RPT_TIMEOUT = True + print("ARQ_RX_RPT_TIMEOUT") + +def arq_frame_timeout(): + if static.ARQ_STATE == 'RECEIVING_SIGNALLING': + static.ARQ_RX_FRAME_TIMEOUT = True + print("ARQ_RX_FRAME_TIMEOUT") + + +def arq_reset_timeout(state): + print(state) + static.ARQ_RX_ACK_TIMEOUT = state + static.ARQ_RX_FRAME_TIMEOUT = state + static.ARQ_RX_RPT_TIMEOUT = state + +def arq_reset_ack(state): + print(state) + static.ARQ_ACK_RECEIVED = state + static.ARQ_RPT_RECEIVED = state + static.ARQ_FRAME_ACK_RECEIVED = state + +def arq_reset_frame_machine(): + arq_reset_timeout(False) + arq_reset_ack(False) + static.TX_N_RETRIES = 0 + static.ARQ_N_SENT_FRAMES = 0 + static.ARQ_TX_N_FRAMES_PER_BURST = 0 + + + From be7bc9744fdfbbcc429dc8db9a00fc774db5bb54 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Wed, 10 Feb 2021 15:05:03 +0100 Subject: [PATCH 07/14] improved states --- arq.py | 159 ++++++++++++++++++++++++++++++++++-------------------- modem.py | 32 +++++++---- static.py | 11 ++-- 3 files changed, 131 insertions(+), 71 deletions(-) diff --git a/arq.py b/arq.py index 193eb702..ef60befd 100644 --- a/arq.py +++ b/arq.py @@ -101,7 +101,7 @@ def data_received(data_in): logging.info("ARQ | TX | BURST ACK") #BUILDING ACK FRAME FOR BURST ----------------------------------------------- - ack_payload = b'ACK FRAME' + ack_payload = b'BURST_ACK' ack_frame = b'<' + ack_payload # < = 60 #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- @@ -176,11 +176,11 @@ def data_received(data_in): static.RX_BUFFER.append(complete_data_frame) #BUILDING ACK FRAME FOR DATA FRAME ----------------------------------------------- - - ack_frame = b'='+ bytes(static.FRAME_CRC) # < = 61 + ack_payload = b'FRAME_ACK' + ack_frame = b'='+ ack_payload + bytes(static.FRAME_CRC) # < = 61 #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- - time.sleep(0.5) #0.5 + time.sleep(3) #0.5 logging.info("ARQ | TX | ARQ DATA FRAME ACK [" + str(static.FRAME_CRC.hex()) +"]") modem.transmit_arq_ack(ack_frame) @@ -200,7 +200,7 @@ def data_received(data_in): logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") - + def transmit(data_out): @@ -230,7 +230,6 @@ def transmit(data_out): static.ARQ_TX_N_FRAMES_PER_BURST = get_n_frames_per_burst() # ----------- CREATE FRAME TOTAL PAYLOAD TO BE ABLE TO CREATE CRC FOR IT - try: # DETECT IF LAST BURST TO PREVENT INDEX ERROR OF BUFFER for i in range(static.ARQ_TX_N_FRAMES_PER_BURST): # Loop through TX_BUFFER LIST @@ -247,10 +246,12 @@ def transmit(data_out): else: static.ARQ_TX_N_FRAMES_PER_BURST = (static.TX_BUFFER_SIZE % static.ARQ_N_SENT_FRAMES) - #--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK RECEPTION FAILS for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES): + + + if static.ARQ_N_SENT_FRAMES + 1 <= static.TX_BUFFER_SIZE: logging.info("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) + "]") @@ -267,27 +268,38 @@ def transmit(data_out): # --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1 #reset timer and ack state - static.ARQ_FRAME_ACK_RECEIVED = False - static.ARQ_ACK_RECEIVED = False - static.ARQ_RX_ACK_TIMEOUT = False + #static.ARQ_FRAME_ACK_RECEIVED = False + #static.ARQ_ACK_RECEIVED = False + #static.ARQ_RX_ACK_TIMEOUT = False + logging.info("ARQ | RX | WAITING FOR BURST ACK") static.ARQ_STATE = 'RECEIVING_SIGNALLING' + + helpers.arq_reset_timeout(False) + helpers.arq_reset_ack(False) - timer = threading.Timer(static.ARQ_RX_ACK_TIMEOUT_SECONDS, helpers.arq_ack_timeout) - timer.start() + acktimer = threading.Timer(static.ARQ_RX_ACK_TIMEOUT_SECONDS, helpers.arq_ack_timeout) + acktimer.start() + + print(".............................") + print("static.ARQ_STATE " + str(static.ARQ_STATE)) + print("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) + print("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) + print("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) + print("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) + print(".............................") # --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN - while (static.ARQ_ACK_RECEIVED == False or static.ARQ_RPT_RECEIVED == False or static.ARQ_FRAME_ACK_RECEIVED == False) and static.ARQ_RX_ACK_TIMEOUT == False: + while static.ARQ_ACK_RECEIVED != True and static.ARQ_RPT_RECEIVED != True and static.ARQ_FRAME_ACK_RECEIVED != True and static.ARQ_RX_FRAME_TIMEOUT != True and static.ARQ_RX_ACK_TIMEOUT != True: time.sleep(0.01) # lets reduce CPU load a little bit - #print(static.ARQ_STATE) - - #-------------------------------------------------------------------------------------------------------------- - + print(static.ARQ_STATE) + if static.ARQ_RPT_RECEIVED == True: logging.info("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) logging.info("ARQ | TX | SENDING REQUESTED FRAMES: " + str(static.ARQ_RPT_FRAMES)) + TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") TRANSMIT_ARQ_BURST_THREAD.start() @@ -295,73 +307,103 @@ def transmit(data_out): while static.ARQ_STATE == 'SENDING_DATA': time.sleep(0.01) - static.ARQ_FRAME_ACK_RECEIVED = False - static.ARQ_ACK_RECEIVED = False - static.ARQ_RX_ACK_TIMEOUT = False - static.ARQ_RX_RPT_TIMEOUT = False - + static.ARQ_STATE = 'RECEIVING_SIGNALLING' - - timer = threading.Timer(static.ARQ_RX_RPT_TIMEOUT_SECONDS, helpers.arq_rpt_timeout) - timer.start() + + helpers.arq_reset_timeout(False) + helpers.arq_reset_ack(False) + + rpttimer = threading.Timer(static.ARQ_RX_RPT_TIMEOUT_SECONDS, helpers.arq_rpt_timeout) + rpttimer.start() while static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_RPT_TIMEOUT == False: time.sleep(0.01) # lets reduce CPU load a little bit - + print(static.ARQ_STATE) + if static.ARQ_ACK_RECEIVED == True: logging.info("ARQ | RX | ACK RECEIVED AFTER FRAME REPEAT") - static.ARQ_RX_ACK_TIMEOUT = True - static.ARQ_RX_RPT_TIMEOUT = True + helpers.arq_reset_ack(True) static.ARQ_RPT_FRAMES = [] if static.ARQ_RX_RPT_TIMEOUT == True and static.ARQ_ACK_RECEIVED == False: print("Burst lost....") - static.ARQ_RPT_RECEIVED = False + + helpers.arq_reset_ack(False) static.ARQ_RPT_FRAMES = [] #-------------------------------------------------------------------------------------------------------------- - #if static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RX_ACK_TIMEOUT == 1: - # #logging.info("ARQ | RX | ACK TIMEOUT | SENDING ARQ BURST AGAIN") - # pass + elif static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RX_ACK_TIMEOUT == 1: + logging.info("ARQ | RX | ACK TIMEOUT - AND NO ACK!") + pass #no break here so we can continue with the next try of repeating the burst #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED - if static.ARQ_ACK_RECEIVED == True: + elif static.ARQ_ACK_RECEIVED == True: logging.info("ARQ | RX | ACK RECEIVED") #-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break #--------------- BREAK LOOP IF FRAME ACK HAS BEEN RECEIVED EARLIER AS EXPECTED - if static.ARQ_FRAME_ACK_RECEIVED == True: + elif static.ARQ_FRAME_ACK_RECEIVED == True: + print("----------------------------------------------------------") logging.info("ARQ | RX | EARLY FRAME ACK RECEIVED - STOPPING TX") #static.ARQ_N_SENT_FRAMES = #static.TX_BUFFER_SIZE static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break - + + else: + print("------------------------------->NO RULE MATCHED!") + break + + + #--------------------------------WAITING AREA FOR FRAME ACKs + + print("static.ARQ_N_SENT_FRAMES " + str(static.ARQ_N_SENT_FRAMES)) + print("static.TX_BUFFER_SIZE " + str(static.TX_BUFFER_SIZE)) + print("static.TX_N_RETRIES " + str(static.TX_N_RETRIES)) + print("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) + + print("static.ARQ_STATE " + str(static.ARQ_STATE)) + print("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) + print("static.ARQ_RX_FRAME_TIMEOUT " + str(static.ARQ_RX_FRAME_TIMEOUT)) + print("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) + print("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) + print("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) + + + frametimer = threading.Timer(static.ARQ_RX_FRAME_TIMEOUT_SECONDS, helpers.arq_frame_timeout) + frametimer.start() + static.ARQ_STATE = 'RECEIVING_SIGNALLING' + + # wait for frame ACK if we processed the last frame/burst + while static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_FRAME_TIMEOUT == False and static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE: + time.sleep(0.01) # lets reduce CPU load a little bit + #print(static.ARQ_STATE) + print("WAITING FOR FRAME ACK") + + + # ----------- if no ACK received and out of retries.....stop frame sending if static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_ACK_TIMEOUT == True: logging.info("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") break #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK - if static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == True: + elif static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == True: logging.info("ARQ | RX | REGULAR FRAME ACK RECEIVED - DATA TRANSMITTED!") break - + + else: + print("NO MATCHING RULE AT THE END") + # IF TX BUFFER IS EMPTY / ALL FRAMES HAVE BEEN SENT --> HERE WE COULD ADD AN static.VAR for IDLE STATE logging.info("ARQ | TX | BUFFER EMPTY") - # - RESET COUNTERS - static.ARQ_N_SENT_FRAMES = 0 - static.ARQ_TX_N_FRAMES_PER_BURST = False - static.ARQ_ACK_RECEIVED = False - static.ARQ_FRAME_ACK_RECEIVED = False - - + helpers.arq_reset_frame_machine() @@ -379,32 +421,33 @@ def get_n_frames_per_burst(): def burst_ack_received(): - #logging.info("ARQ | RX | BURST ACK RCVD!") - static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting + logging.info("ARQ | RX | BURST ACK RCVD!") + #static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting static.ARQ_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame - static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting - static.ARQ_RPT_RECEIVED = False - static.ARQ_RPT_FRAMES = [] + #static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting + #static.ARQ_RPT_RECEIVED = False + #static.ARQ_RPT_FRAMES = [] def frame_ack_received(): - #logging.info("ARQ | RX | FRAME ACK RCVD!") - static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting + logging.info("ARQ | RX | FRAME ACK RCVD!") + #static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting static.ARQ_FRAME_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame - static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting - static.ARQ_RPT_RECEIVED = False - static.ARQ_RPT_FRAMES = [] - + #static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting + #static.ARQ_RPT_RECEIVED = False + #static.ARQ_RPT_FRAMES = [] + def burst_rpt_received(data_in): - #logging.info("ARQ | RX | BURST RPT RCVD!") - static.ARQ_RX_ACK_TIMEOUT = False #Force timer to stop waiting - static.ARQ_ACK_RECEIVED = False #Force data loops of TNC to stop and continue with next frame + logging.info("ARQ | RX | BURST RPT RCVD!") + #static.ARQ_RX_ACK_TIMEOUT = False #Force timer to stop waiting + #static.ARQ_ACK_RECEIVED = False #Force data loops of TNC to stop and continue with next frame + #static.ARQ_RX_RPT_TIMEOUT = True static.ARQ_RPT_RECEIVED = True static.ARQ_RPT_FRAMES = [] diff --git a/modem.py b/modem.py index 24e13540..71191378 100644 --- a/modem.py +++ b/modem.py @@ -90,9 +90,15 @@ class RF(): txbuffer += bytes(mod_out) txbuffer = txbuffer.rstrip(b'\x00') #lets remove unallocated memory because of wrong buffer :-/ - # -------------- transmit audio twice + # -------------- transmit audio twice + + print("SEND SIGNALLING FRAME...................................") + print(ack_buffer) self.stream_tx.write(bytes(txbuffer)) + print("........................................................") self.stream_tx.write(bytes(txbuffer)) + + print("...................................DONE!") static.ARQ_STATE = 'RECEIVING_DATA' #-------------------------------------------------------------------------------------------------------- @@ -196,7 +202,7 @@ class RF(): # -------------- transmit audio self.stream_tx.write(bytes(txbuffer)) - + #time.sleep(0.5) static.ARQ_STATE = 'IDLE' #static.ARQ_STATE = 'RECEIVING_SIGNALLING' @@ -242,7 +248,7 @@ class RF(): 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 - #print(self.c_lib.freedv_get_rx_status(freedv_data)) + print(self.c_lib.freedv_get_rx_status(freedv_data)) #-------------STUCK IN SYNC DETECTOR @@ -261,7 +267,7 @@ class RF(): if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2: - print("stuck in sync #2 --> DOING UNSYNC") + logging.warning("modem stuck in sync") self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC stuck_in_sync_counter = 0 stuck_in_sync_10_counter = 0 @@ -324,20 +330,26 @@ class RF(): # BURST ACK if frametype == 60: + print("ACK RECEIVED....") arq.burst_ack_received() # FRAME ACK - if frametype == 61: + elif frametype == 61: + print("FRAME ACK RECEIVED....") arq.frame_ack_received() # FRAME RPT - if frametype == 62: + elif frametype == 62: + print("REPEAT REQUEST RECEIVED....") arq.burst_rpt_received(signalling_bytes_out[:-2]) - + else: + print("OTHER FRAME: " + str(signalling_bytes_out[:-2])) + + rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) - #print("ACK") + print("ACK-" + str(rxstatus)) #print(rxstatus) - #if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME:# or rxstatus == 10: - # self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC + if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10: + self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC diff --git a/static.py b/static.py index b7570668..0eb4d840 100644 --- a/static.py +++ b/static.py @@ -84,12 +84,17 @@ ARQ_N_RX_FRAMES_PER_BURSTS = 0 # NUMBER OF FRAMES WE ARE WAITING FOR --> GOT DAT ARQ_ACK_PAYLOAD_PER_FRAME = 0 # PAYLOAD per ACK frame ARQ_ACK_RECEIVED = False # set to 1 if ACK received -ARQ_FRAME_ACK_RECEIVED = False # set to 1 if FRAME ACK received ARQ_RX_ACK_TIMEOUT = False # set to 1 if timeut reached -ARQ_RX_ACK_TIMEOUT_SECONDS = 6.0 #timeout for waiting for ACK frames +ARQ_RX_ACK_TIMEOUT_SECONDS = 4.0 #timeout for waiting for ACK frames + + +ARQ_FRAME_ACK_RECEIVED = False # set to 1 if FRAME ACK received +ARQ_RX_FRAME_TIMEOUT = False +ARQ_RX_FRAME_TIMEOUT_SECONDS = 4.0 + ARQ_RX_RPT_TIMEOUT = False -ARQ_RX_RPT_TIMEOUT_SECONDS = 6.0 +ARQ_RX_RPT_TIMEOUT_SECONDS = 4.0 ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received ARQ_RPT_FRAMES = [] #buffer for frames which are requested to repeat From 63628f56d33807f65f153f6dee2321f96bedacbe Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Wed, 10 Feb 2021 19:43:59 +0100 Subject: [PATCH 08/14] improved logging now with colors and timestamps... --- arq.py | 79 +++++++++++++++++++++++++++--------------------------- helpers.py | 16 ++++++----- main.py | 56 +++++++++++++++++++++++++++++++------- modem.py | 31 +++++++++++---------- static.py | 6 ++--- 5 files changed, 113 insertions(+), 75 deletions(-) diff --git a/arq.py b/arq.py index ef60befd..92490a2d 100644 --- a/arq.py +++ b/arq.py @@ -14,7 +14,10 @@ from random import randrange import static import modem import helpers -import main +#import main + + + modem = modem.RF() @@ -22,12 +25,7 @@ modem = modem.RF() static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 3 #6?! static.ARQ_ACK_PAYLOAD_PER_FRAME = 14 - 2# -#def arq_ack_timeout(): -# static.ARQ_ACK_TIMEOUT = 1 -#def arq_rpt_timeout(): -# static.ARQ_RPT_TIMEOUT = True - def data_received(data_in): @@ -122,7 +120,7 @@ def data_received(data_in): frame_number = burstnumber.to_bytes(2, byteorder='big') missing_frames += frame_number - logging.info("ARQ | TX | RPT ARQ FRAMES [" + str(missing_frames) + "]") + logging.warning("ARQ | TX | RPT ARQ FRAMES [" + str(missing_frames) + "]") #BUILDING RPT FRAME FOR BURST ----------------------------------------------- rpt_payload = missing_frames @@ -180,7 +178,7 @@ def data_received(data_in): ack_frame = b'='+ ack_payload + bytes(static.FRAME_CRC) # < = 61 #TRANSMIT ACK FRAME FOR BURST----------------------------------------------- - time.sleep(3) #0.5 + time.sleep(1) #0.5 logging.info("ARQ | TX | ARQ DATA FRAME ACK [" + str(static.FRAME_CRC.hex()) +"]") modem.transmit_arq_ack(ack_frame) @@ -197,7 +195,7 @@ def data_received(data_in): #print("----------------------------------------------------------------") else: - logging.info("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") + logging.error("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") @@ -273,7 +271,7 @@ def transmit(data_out): #static.ARQ_RX_ACK_TIMEOUT = False - logging.info("ARQ | RX | WAITING FOR BURST ACK") + logging.debug("ARQ | RX | WAITING FOR BURST ACK") static.ARQ_STATE = 'RECEIVING_SIGNALLING' helpers.arq_reset_timeout(False) @@ -282,22 +280,22 @@ def transmit(data_out): acktimer = threading.Timer(static.ARQ_RX_ACK_TIMEOUT_SECONDS, helpers.arq_ack_timeout) acktimer.start() - print(".............................") - print("static.ARQ_STATE " + str(static.ARQ_STATE)) - print("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) - print("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) - print("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) - print("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) - print(".............................") + logging.debug(".............................") + logging.debug("static.ARQ_STATE " + str(static.ARQ_STATE)) + logging.debug("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) + logging.debug("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) + logging.debug("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) + logging.debug("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) + logging.debug(".............................") # --------------------------- WHILE TIMEOUT NOT REACHED AND NO ACK RECEIVED --> LISTEN while static.ARQ_ACK_RECEIVED != True and static.ARQ_RPT_RECEIVED != True and static.ARQ_FRAME_ACK_RECEIVED != True and static.ARQ_RX_FRAME_TIMEOUT != True and static.ARQ_RX_ACK_TIMEOUT != True: time.sleep(0.01) # lets reduce CPU load a little bit - print(static.ARQ_STATE) + logging.debug(static.ARQ_STATE) if static.ARQ_RPT_RECEIVED == True: - logging.info("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) + logging.warning("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) logging.info("ARQ | TX | SENDING REQUESTED FRAMES: " + str(static.ARQ_RPT_FRAMES)) TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") @@ -318,7 +316,7 @@ def transmit(data_out): while static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_RPT_TIMEOUT == False: time.sleep(0.01) # lets reduce CPU load a little bit - print(static.ARQ_STATE) + logging.debug(static.ARQ_STATE) if static.ARQ_ACK_RECEIVED == True: @@ -328,7 +326,8 @@ def transmit(data_out): static.ARQ_RPT_FRAMES = [] if static.ARQ_RX_RPT_TIMEOUT == True and static.ARQ_ACK_RECEIVED == False: - print("Burst lost....") + + logging.error("ARQ | Burst lost....") helpers.arq_reset_ack(False) static.ARQ_RPT_FRAMES = [] @@ -336,7 +335,7 @@ def transmit(data_out): #-------------------------------------------------------------------------------------------------------------- elif static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RX_ACK_TIMEOUT == 1: - logging.info("ARQ | RX | ACK TIMEOUT - AND NO ACK!") + logging.warning("ARQ | RX | ACK TIMEOUT - AND NO ACK!") pass #no break here so we can continue with the next try of repeating the burst #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED @@ -348,30 +347,30 @@ def transmit(data_out): #--------------- BREAK LOOP IF FRAME ACK HAS BEEN RECEIVED EARLIER AS EXPECTED elif static.ARQ_FRAME_ACK_RECEIVED == True: - print("----------------------------------------------------------") + logging.info("----------------------------------------------------------") logging.info("ARQ | RX | EARLY FRAME ACK RECEIVED - STOPPING TX") #static.ARQ_N_SENT_FRAMES = #static.TX_BUFFER_SIZE static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break else: - print("------------------------------->NO RULE MATCHED!") + logging.debug("------------------------------->NO RULE MATCHED!") break #--------------------------------WAITING AREA FOR FRAME ACKs - print("static.ARQ_N_SENT_FRAMES " + str(static.ARQ_N_SENT_FRAMES)) - print("static.TX_BUFFER_SIZE " + str(static.TX_BUFFER_SIZE)) - print("static.TX_N_RETRIES " + str(static.TX_N_RETRIES)) - print("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) + logging.debug("static.ARQ_N_SENT_FRAMES " + str(static.ARQ_N_SENT_FRAMES)) + logging.debug("static.TX_BUFFER_SIZE " + str(static.TX_BUFFER_SIZE)) + logging.debug("static.TX_N_RETRIES " + str(static.TX_N_RETRIES)) + logging.debug("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) - print("static.ARQ_STATE " + str(static.ARQ_STATE)) - print("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) - print("static.ARQ_RX_FRAME_TIMEOUT " + str(static.ARQ_RX_FRAME_TIMEOUT)) - print("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) - print("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) - print("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) + logging.debug("static.ARQ_STATE " + str(static.ARQ_STATE)) + logging.debug("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) + logging.debug("static.ARQ_RX_FRAME_TIMEOUT " + str(static.ARQ_RX_FRAME_TIMEOUT)) + logging.debug("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) + logging.debug("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) + logging.debug("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) frametimer = threading.Timer(static.ARQ_RX_FRAME_TIMEOUT_SECONDS, helpers.arq_frame_timeout) @@ -382,13 +381,13 @@ def transmit(data_out): while static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_FRAME_TIMEOUT == False and static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE: time.sleep(0.01) # lets reduce CPU load a little bit #print(static.ARQ_STATE) - print("WAITING FOR FRAME ACK") + logging.debug("WAITING FOR FRAME ACK") # ----------- if no ACK received and out of retries.....stop frame sending if static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_ACK_TIMEOUT == True: - logging.info("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") + logging.error("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") break #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK @@ -397,7 +396,7 @@ def transmit(data_out): break else: - print("NO MATCHING RULE AT THE END") + logging.debug("NO MATCHING RULE AT THE END") # IF TX BUFFER IS EMPTY / ALL FRAMES HAVE BEEN SENT --> HERE WE COULD ADD AN static.VAR for IDLE STATE @@ -421,7 +420,7 @@ def get_n_frames_per_burst(): def burst_ack_received(): - logging.info("ARQ | RX | BURST ACK RCVD!") + #logging.info("ARQ | RX | BURST ACK RCVD!") #static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting static.ARQ_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame @@ -432,7 +431,7 @@ def burst_ack_received(): def frame_ack_received(): - logging.info("ARQ | RX | FRAME ACK RCVD!") + #logging.info("ARQ | RX | FRAME ACK RCVD!") #static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting static.ARQ_FRAME_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame @@ -443,7 +442,7 @@ def frame_ack_received(): def burst_rpt_received(data_in): - logging.info("ARQ | RX | BURST RPT RCVD!") + #logging.info("ARQ | RX | BURST RPT RCVD!") #static.ARQ_RX_ACK_TIMEOUT = False #Force timer to stop waiting #static.ARQ_ACK_RECEIVED = False #Force data loops of TNC to stop and continue with next frame diff --git a/helpers.py b/helpers.py index d2b2d1e3..10447e46 100644 --- a/helpers.py +++ b/helpers.py @@ -9,12 +9,14 @@ Created on Fri Dec 25 21:25:14 2020 import time import threading import logging +from colorlog import ColoredFormatter import crcengine import static - + + def get_crc_8(data): crc_algorithm = crcengine.new('crc8-ccitt') #load crc8 library @@ -32,29 +34,29 @@ def get_crc_16(data): def arq_ack_timeout(): if static.ARQ_STATE == 'RECEIVING_SIGNALLING': static.ARQ_RX_ACK_TIMEOUT = True - print("ARQ_RX_ACK_TIMEOUT") + logging.debug("ARQ_RX_ACK_TIMEOUT") def arq_rpt_timeout(): if static.ARQ_STATE == 'RECEIVING_SIGNALLING': static.ARQ_RX_RPT_TIMEOUT = True - print("ARQ_RX_RPT_TIMEOUT") + logging.debug("ARQ_RX_RPT_TIMEOUT") def arq_frame_timeout(): if static.ARQ_STATE == 'RECEIVING_SIGNALLING': static.ARQ_RX_FRAME_TIMEOUT = True - print("ARQ_RX_FRAME_TIMEOUT") + logging.debug("ARQ_RX_FRAME_TIMEOUT") def arq_reset_timeout(state): - print(state) + static.ARQ_RX_ACK_TIMEOUT = state static.ARQ_RX_FRAME_TIMEOUT = state static.ARQ_RX_RPT_TIMEOUT = state def arq_reset_ack(state): - print(state) + static.ARQ_ACK_RECEIVED = state static.ARQ_RPT_RECEIVED = state static.ARQ_FRAME_ACK_RECEIVED = state @@ -66,6 +68,6 @@ def arq_reset_frame_machine(): static.ARQ_N_SENT_FRAMES = 0 static.ARQ_TX_N_FRAMES_PER_BURST = 0 - + diff --git a/main.py b/main.py index 8fdc7b28..e86710f6 100644 --- a/main.py +++ b/main.py @@ -11,8 +11,10 @@ import socketserver import argparse import logging + #import tnc import static +import helpers @@ -21,32 +23,68 @@ import static if __name__ == '__main__': + + + + static.MYCALLSIGN = b'DJ2LS' + static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) + + static.DXCALLSIGN = b'DH3WO' + static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) + + print("MYCALLSIGN " + str(static.MYCALLSIGN)) + print("MYCALLSIGN_CRC8 " + str(static.MYCALLSIGN_CRC8)) + + print("DXCALLSIGN " + str(static.DXCALLSIGN)) + print("DXCALLSIGN_CRC8 " + str(static.DXCALLSIGN_CRC8)) + + + #--------------------------------------------GET PARAMETER INPUTS parser = argparse.ArgumentParser(description='Simons TEST TNC') parser.add_argument('--rx', dest="audio_input_device", default=0, help="sound card for listening.", type=int) parser.add_argument('--tx', dest="audio_output_device", default=0, help="sound card for transmitting.", type=int) parser.add_argument('--port', dest="socket_port", default=3000, help="Set the port, the socket is listening on.", type=int) - + parser.add_argument('--mode', dest="freedv_data_mode", default=12, help="Set the mode.", type=int) + args = parser.parse_args() - + + + + static.FREEDV_DATA_MODE = args.freedv_data_mode static.AUDIO_INPUT_DEVICE = args.audio_input_device static.AUDIO_OUTPUT_DEVICE = args.audio_output_device static.PORT = args.socket_port import tnc # we need to wait until we got all parameters from argparse - #-------------------------------------------- DEFINE LOGGER - logger = logging.getLogger() - logger.setLevel("INFO") #DEBUG>INFO>WARNING>ERROR>CRITICAL + #-------------------------------------------- DEFINE LOGGING + logging.basicConfig(format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', datefmt='%H:%M:%S', level=logging.INFO) + #logging.addLevelName(logging.INFO, "\033[1;37m%s\033[1;0m" % 'SUCCESS') - - - #--------------------------------------------START SERVER - logging.info("STARTING TCP/IP SOCKET ON PORT " + str(static.PORT)) + logging.addLevelName( logging.DEBUG, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) + logging.addLevelName( logging.INFO, "\033[1;32m%s\033[1;0m" % logging.getLevelName(logging.INFO)) + logging.addLevelName( logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) + logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) + logging.addLevelName( logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL)) + + + # https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output + #'DEBUG' : 37, # white + #'INFO' : 36, # cyan + #'WARNING' : 33, # yellow + #'ERROR' : 31, # red + #'CRITICAL': 41, # white on red bg + + + #--------------------------------------------START CMD SERVER + logging.info("SRV | STARTING TCP/IP SOCKET ON PORT " + str(static.PORT)) try: socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 server = socketserver.TCPServer((static.HOST, static.PORT), tnc.TCPRequestHandler) server.serve_forever() finally: server.server_close() + + diff --git a/modem.py b/modem.py index 71191378..6a9dd11c 100644 --- a/modem.py +++ b/modem.py @@ -92,13 +92,12 @@ class RF(): # -------------- transmit audio twice - print("SEND SIGNALLING FRAME...................................") - print(ack_buffer) - self.stream_tx.write(bytes(txbuffer)) - print("........................................................") + logging.debug("SEND SIGNALLING FRAME " + str(ack_buffer)) self.stream_tx.write(bytes(txbuffer)) - print("...................................DONE!") + self.stream_tx.write(bytes(txbuffer)) + + static.ARQ_STATE = 'RECEIVING_DATA' #-------------------------------------------------------------------------------------------------------- @@ -248,7 +247,7 @@ class RF(): 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 - print(self.c_lib.freedv_get_rx_status(freedv_data)) + logging.debug(self.c_lib.freedv_get_rx_status(freedv_data)) #-------------STUCK IN SYNC DETECTOR @@ -267,7 +266,7 @@ class RF(): if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2: - logging.warning("modem stuck in sync") + logging.critical("modem stuck in sync") self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC stuck_in_sync_counter = 0 stuck_in_sync_10_counter = 0 @@ -293,19 +292,19 @@ class RF(): #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: - print("FULL BURST BUFFER ---> UNSYNC") + logging.debug("FULL BURST BUFFER ---> UNSYNC") self.c_lib.freedv_set_sync(freedv_data, 0) else: - print("---------------------------SIMULATED MISSING FRAME") + logging.critical("---------------------------SIMULATED MISSING FRAME") force = True else: - print("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out))) + 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: - print("LAST FRAME ---> UNSYNC") + logging.debug("LAST FRAME ---> UNSYNC") self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC @@ -330,25 +329,25 @@ class RF(): # BURST ACK if frametype == 60: - print("ACK RECEIVED....") + logging.debug("ACK RECEIVED....") arq.burst_ack_received() # FRAME ACK elif frametype == 61: - print("FRAME ACK RECEIVED....") + logging.debug("FRAME ACK RECEIVED....") arq.frame_ack_received() # FRAME RPT elif frametype == 62: - print("REPEAT REQUEST RECEIVED....") + logging.debug("REPEAT REQUEST RECEIVED....") arq.burst_rpt_received(signalling_bytes_out[:-2]) else: - print("OTHER FRAME: " + str(signalling_bytes_out[:-2])) + logging.debug("OTHER FRAME: " + str(signalling_bytes_out[:-2])) rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) - print("ACK-" + str(rxstatus)) + logging.debug("ACK-" + str(rxstatus)) #print(rxstatus) if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10: self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC diff --git a/static.py b/static.py index 0eb4d840..4fa71047 100644 --- a/static.py +++ b/static.py @@ -85,16 +85,16 @@ ARQ_ACK_PAYLOAD_PER_FRAME = 0 # PAYLOAD per ACK frame ARQ_ACK_RECEIVED = False # set to 1 if ACK received ARQ_RX_ACK_TIMEOUT = False # set to 1 if timeut reached -ARQ_RX_ACK_TIMEOUT_SECONDS = 4.0 #timeout for waiting for ACK frames +ARQ_RX_ACK_TIMEOUT_SECONDS = 5.0 #timeout for waiting for ACK frames ARQ_FRAME_ACK_RECEIVED = False # set to 1 if FRAME ACK received ARQ_RX_FRAME_TIMEOUT = False -ARQ_RX_FRAME_TIMEOUT_SECONDS = 4.0 +ARQ_RX_FRAME_TIMEOUT_SECONDS = 5.0 ARQ_RX_RPT_TIMEOUT = False -ARQ_RX_RPT_TIMEOUT_SECONDS = 4.0 +ARQ_RX_RPT_TIMEOUT_SECONDS = 5.0 ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received ARQ_RPT_FRAMES = [] #buffer for frames which are requested to repeat From 81cbb427e7fce2acc9688bb00074e210a32a820f Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Wed, 10 Feb 2021 21:30:46 +0100 Subject: [PATCH 09/14] erase frame buffer if first frame prevent a buffer issue if a transmission is stuck and we receive a new data frame --- arq.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arq.py b/arq.py index 92490a2d..8dbdd4b0 100644 --- a/arq.py +++ b/arq.py @@ -64,6 +64,10 @@ def data_received(data_in): #allocate ARQ_RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a data frame to N list position so we can explicit search for it + # delete frame buffer if first frame to make sure the buffer is cleared and no junks of a old frame is remaining + if static.ARQ_RX_N_CURRENT_ARQ_FRAME == 1: + static.ARQ_RX_FRAME_BUFFER = [] + try: static.ARQ_RX_FRAME_BUFFER[static.ARQ_RX_N_CURRENT_ARQ_FRAME] = bytes(data_in) @@ -295,7 +299,7 @@ def transmit(data_out): if static.ARQ_RPT_RECEIVED == True: - logging.warning("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) + logging.warning("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) logging.info("ARQ | TX | SENDING REQUESTED FRAMES: " + str(static.ARQ_RPT_FRAMES)) TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") @@ -320,7 +324,7 @@ def transmit(data_out): if static.ARQ_ACK_RECEIVED == True: - logging.info("ARQ | RX | ACK RECEIVED AFTER FRAME REPEAT") + logging.info("ARQ | RX | ACK AFTER RPT") helpers.arq_reset_ack(True) static.ARQ_RPT_FRAMES = [] @@ -340,7 +344,7 @@ def transmit(data_out): #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED elif static.ARQ_ACK_RECEIVED == True: - logging.info("ARQ | RX | ACK RECEIVED") + logging.info("ARQ | RX | ACK") #-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break @@ -392,7 +396,7 @@ def transmit(data_out): #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK elif static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == True: - logging.info("ARQ | RX | REGULAR FRAME ACK RECEIVED - DATA TRANSMITTED!") + logging.info("ARQ | RX | FRAME ACK RECEIVED - DATA TRANSMITTED! :-)") break else: @@ -412,8 +416,8 @@ def transmit(data_out): # BURST MACHINE TO DEFINE N BURSTS PER FRAME ---> LATER WE CAN USE CHANNEL MESSUREMENT TO SET FRAMES PER BURST def get_n_frames_per_burst(): - #n_frames_per_burst = randrange(1,10) - n_frames_per_burst = 4 + n_frames_per_burst = randrange(1,10) + #n_frames_per_burst = 4 return n_frames_per_burst From 129e0c06450ef9bb5e5e04d39d44789819f0c467 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Mon, 15 Feb 2021 16:33:43 +0100 Subject: [PATCH 10/14] improved single frame transmission solved timing issues --- arq.py | 112 +++++++++++++++++++++++++---------------------------- helpers.py | 16 ++------ main.py | 74 +++++++++++++++++++++++++++-------- modem.py | 23 +++++------ 4 files changed, 126 insertions(+), 99 deletions(-) diff --git a/arq.py b/arq.py index 8dbdd4b0..4855155e 100644 --- a/arq.py +++ b/arq.py @@ -14,8 +14,8 @@ from random import randrange import static import modem import helpers -#import main +#import tnc @@ -57,7 +57,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.info("ARQ | RX | ARQ FRAME [" + str(static.ARQ_N_FRAME) + "/" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS) + "] [" + str(arq_percent_burst).zfill(3) + "%] --- TOTAL [" + 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 | ARQ FRAME [" + str(static.ARQ_N_FRAME) + "/" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS) + "] [" + str(arq_percent_burst).zfill(3) + "%] --- TOTAL [" + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME) + "/" + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) + "] [" + str(arq_percent_frame).zfill(3) + "%]" ) @@ -121,7 +121,13 @@ def data_received(data_in): for burstnumber in range(1,len(static.ARQ_RX_BURST_BUFFER)): if static.ARQ_RX_BURST_BUFFER[burstnumber] == None: - frame_number = burstnumber.to_bytes(2, byteorder='big') + #frame_number = static.ARQ_RX_N_CURRENT_ARQ_FRAME - static.ARQ_N_RX_FRAMES_PER_BURSTS + burstnumber + #logging.debug("frame_number" + str(frame_number)) + logging.debug("static.ARQ_RX_N_CURRENT_ARQ_FRAME" + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME)) + logging.debug("ARQ_N_RX_FRAMES_PER_BURSTS" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS)) + + frame_number = burstnumber + frame_number = frame_number.to_bytes(2, byteorder='big') missing_frames += frame_number logging.warning("ARQ | TX | RPT ARQ FRAMES [" + str(missing_frames) + "]") @@ -173,7 +179,8 @@ def data_received(data_in): #IF THE FRAME PAYLOAD CRC IS EQUAL TO THE FRAME CRC WHICH IS KNOWN FROM THE HEADER --> SUCCESS if frame_payload_crc == static.FRAME_CRC: - logging.info("ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED! - TIME TO PARTY") + #logging.info("ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED! - TIME TO PARTY") + logging.log(25,"ARQ | RX | DATA FRAME SUCESSFULLY RECEIVED! - TIME TO PARTY") #append received frame to RX_BUFFER static.RX_BUFFER.append(complete_data_frame) @@ -195,7 +202,8 @@ def data_received(data_in): static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0 #print("----------------------------------------------------------------") - #print(static.RX_BUFFER[-1]) + #print(static.RX_BUFFER[-1]) + #tnc.request.sendall(bytes(static.RX_BUFFER[-1])) #print("----------------------------------------------------------------") else: @@ -250,12 +258,9 @@ def transmit(data_out): #--------------------------------------------- N ATTEMPTS TO SEND BURSTS IF ACK RECEPTION FAILS for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES): - - - - + if static.ARQ_N_SENT_FRAMES + 1 <= static.TX_BUFFER_SIZE: - logging.info("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 | 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 @@ -265,15 +270,8 @@ def transmit(data_out): # lets wait during sending. After sending is finished we will continue while static.ARQ_STATE == 'SENDING_DATA': time.sleep(0.01) - #print("sending.....") - - + # --------------------------- START TIMER FOR WAITING FOR ACK ---> IF TIMEOUT REACHED, ACK_TIMEOUT = 1 - #reset timer and ack state - #static.ARQ_FRAME_ACK_RECEIVED = False - #static.ARQ_ACK_RECEIVED = False - #static.ARQ_RX_ACK_TIMEOUT = False - logging.debug("ARQ | RX | WAITING FOR BURST ACK") static.ARQ_STATE = 'RECEIVING_SIGNALLING' @@ -300,7 +298,7 @@ def transmit(data_out): if static.ARQ_RPT_RECEIVED == True: logging.warning("ARQ | RX | REQUEST FOR REPEATING FRAMES: " + str(static.ARQ_RPT_FRAMES)) - logging.info("ARQ | TX | SENDING REQUESTED FRAMES: " + str(static.ARQ_RPT_FRAMES)) + logging.warning("ARQ | TX | SENDING REQUESTED FRAMES: " + str(static.ARQ_RPT_FRAMES)) TRANSMIT_ARQ_BURST_THREAD = threading.Thread(target=modem.transmit_arq_burst, name="TRANSMIT_ARQ_BURST") TRANSMIT_ARQ_BURST_THREAD.start() @@ -325,7 +323,7 @@ def transmit(data_out): if static.ARQ_ACK_RECEIVED == True: logging.info("ARQ | RX | ACK AFTER RPT") - + rpttimer.cancel() helpers.arq_reset_ack(True) static.ARQ_RPT_FRAMES = [] @@ -339,12 +337,13 @@ def transmit(data_out): #-------------------------------------------------------------------------------------------------------------- elif static.ARQ_ACK_RECEIVED == 0 and static.ARQ_RX_ACK_TIMEOUT == 1: - logging.warning("ARQ | RX | ACK TIMEOUT - AND NO ACK!") + logging.warning("ARQ | RX | ACK TIMEOUT!") pass #no break here so we can continue with the next try of repeating the burst #--------------- BREAK LOOP IF ACK HAS BEEN RECEIVED elif static.ARQ_ACK_RECEIVED == True: - logging.info("ARQ | RX | ACK") + logging.info("ARQ | RX | ACK") + acktimer.cancel() #-----------IF ACK RECEIVED, INCREMENT ITERATOR FOR MAIN LOOP TO PROCEED WITH NEXT FRAMES/BURST static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break @@ -352,7 +351,8 @@ def transmit(data_out): #--------------- BREAK LOOP IF FRAME ACK HAS BEEN RECEIVED EARLIER AS EXPECTED elif static.ARQ_FRAME_ACK_RECEIVED == True: logging.info("----------------------------------------------------------") - logging.info("ARQ | RX | EARLY FRAME ACK RECEIVED - STOPPING TX") + logging.info("ARQ | RX | EARLY FRAME ACK RECEIVED") + #static.ARQ_N_SENT_FRAMES = #static.TX_BUFFER_SIZE static.ARQ_N_SENT_FRAMES = static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST break @@ -364,18 +364,18 @@ def transmit(data_out): #--------------------------------WAITING AREA FOR FRAME ACKs - logging.debug("static.ARQ_N_SENT_FRAMES " + str(static.ARQ_N_SENT_FRAMES)) - logging.debug("static.TX_BUFFER_SIZE " + str(static.TX_BUFFER_SIZE)) - logging.debug("static.TX_N_RETRIES " + str(static.TX_N_RETRIES)) - logging.debug("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) + logging.debug("static.ARQ_N_SENT_FRAMES " + str(static.ARQ_N_SENT_FRAMES)) + logging.debug("static.TX_BUFFER_SIZE " + str(static.TX_BUFFER_SIZE)) + logging.debug("static.TX_N_RETRIES " + str(static.TX_N_RETRIES)) + logging.debug("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) - logging.debug("static.ARQ_STATE " + str(static.ARQ_STATE)) - logging.debug("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) - logging.debug("static.ARQ_RX_FRAME_TIMEOUT " + str(static.ARQ_RX_FRAME_TIMEOUT)) - logging.debug("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) - logging.debug("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) - logging.debug("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) - + logging.debug("static.ARQ_STATE " + str(static.ARQ_STATE)) + logging.debug("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) + logging.debug("static.ARQ_RX_FRAME_TIMEOUT " + str(static.ARQ_RX_FRAME_TIMEOUT)) + logging.debug("static.ARQ_ACK_RECEIVED " + str(static.ARQ_ACK_RECEIVED)) + logging.debug("static.ARQ_RX_ACK_TIMEOUT " + str(static.ARQ_RX_ACK_TIMEOUT)) + logging.debug("static.ARQ_RPT_RECEIVED " + str(static.ARQ_RPT_RECEIVED)) + logging.debug("static.ARQ_TX_N_FRAMES_PER_BURST " + str(static.ARQ_TX_N_FRAMES_PER_BURST)) frametimer = threading.Timer(static.ARQ_RX_FRAME_TIMEOUT_SECONDS, helpers.arq_frame_timeout) frametimer.start() @@ -386,23 +386,32 @@ def transmit(data_out): time.sleep(0.01) # lets reduce CPU load a little bit #print(static.ARQ_STATE) logging.debug("WAITING FOR FRAME ACK") - - + # ----------- if no ACK received and out of retries.....stop frame sending if static.ARQ_ACK_RECEIVED == False and static.ARQ_FRAME_ACK_RECEIVED == False and static.ARQ_RX_ACK_TIMEOUT == True: - logging.error("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") - break + logging.error("ARQ | TX | NO BURST OR FRAME ACK RECEIVED | DATA SHOULD BE RESEND!") + break #-------------------------BREAK TX BUFFER LOOP IF ALL PACKETS HAVE BEEN SENT AND WE GOT A FRAME ACK elif static.ARQ_N_SENT_FRAMES == static.TX_BUFFER_SIZE and static.ARQ_FRAME_ACK_RECEIVED == True: - logging.info("ARQ | RX | FRAME ACK RECEIVED - DATA TRANSMITTED! :-)") + logging.log(25,"ARQ | RX | FRAME ACK RECEIVED - DATA TRANSMITTED! :-)") break else: logging.debug("NO MATCHING RULE AT THE END") - + # stop all timers + try: + frametimer.cancel() + except Exception: + pass + + try: + acktimer.cancel() + except Exception: + pass + # IF TX BUFFER IS EMPTY / ALL FRAMES HAVE BEEN SENT --> HERE WE COULD ADD AN static.VAR for IDLE STATE logging.info("ARQ | TX | BUFFER EMPTY") @@ -416,41 +425,26 @@ def transmit(data_out): # BURST MACHINE TO DEFINE N BURSTS PER FRAME ---> LATER WE CAN USE CHANNEL MESSUREMENT TO SET FRAMES PER BURST def get_n_frames_per_burst(): - n_frames_per_burst = randrange(1,10) - #n_frames_per_burst = 4 + #n_frames_per_burst = randrange(1,10) + n_frames_per_burst = 2 return n_frames_per_burst def burst_ack_received(): - #logging.info("ARQ | RX | BURST ACK RCVD!") - #static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting static.ARQ_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame - - #static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting - #static.ARQ_RPT_RECEIVED = False - #static.ARQ_RPT_FRAMES = [] + def frame_ack_received(): - #logging.info("ARQ | RX | FRAME ACK RCVD!") - #static.ARQ_RX_ACK_TIMEOUT = True #Force timer to stop waiting static.ARQ_FRAME_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame - - #static.ARQ_RX_RPT_TIMEOUT = True #Force timer to stop waiting - #static.ARQ_RPT_RECEIVED = False - #static.ARQ_RPT_FRAMES = [] + def burst_rpt_received(data_in): - #logging.info("ARQ | RX | BURST RPT RCVD!") - #static.ARQ_RX_ACK_TIMEOUT = False #Force timer to stop waiting - #static.ARQ_ACK_RECEIVED = False #Force data loops of TNC to stop and continue with next frame - - #static.ARQ_RX_RPT_TIMEOUT = True static.ARQ_RPT_RECEIVED = True static.ARQ_RPT_FRAMES = [] diff --git a/helpers.py b/helpers.py index 10447e46..d821851a 100644 --- a/helpers.py +++ b/helpers.py @@ -12,10 +12,10 @@ import logging from colorlog import ColoredFormatter import crcengine - import static + def get_crc_8(data): @@ -28,16 +28,13 @@ def get_crc_16(data): crc_algorithm = crcengine.new('crc16-ccitt-false') #load crc16 library crc_data = crc_algorithm(data) crc_data = crc_data.to_bytes(2, byteorder='big') - return crc_data - + return crc_data def arq_ack_timeout(): if static.ARQ_STATE == 'RECEIVING_SIGNALLING': static.ARQ_RX_ACK_TIMEOUT = True logging.debug("ARQ_RX_ACK_TIMEOUT") - - def arq_rpt_timeout(): if static.ARQ_STATE == 'RECEIVING_SIGNALLING': static.ARQ_RX_RPT_TIMEOUT = True @@ -47,16 +44,13 @@ def arq_frame_timeout(): if static.ARQ_STATE == 'RECEIVING_SIGNALLING': static.ARQ_RX_FRAME_TIMEOUT = True logging.debug("ARQ_RX_FRAME_TIMEOUT") - - + def arq_reset_timeout(state): - static.ARQ_RX_ACK_TIMEOUT = state static.ARQ_RX_FRAME_TIMEOUT = state static.ARQ_RX_RPT_TIMEOUT = state -def arq_reset_ack(state): - +def arq_reset_ack(state): static.ARQ_ACK_RECEIVED = state static.ARQ_RPT_RECEIVED = state static.ARQ_FRAME_ACK_RECEIVED = state @@ -69,5 +63,3 @@ def arq_reset_frame_machine(): static.ARQ_TX_N_FRAMES_PER_BURST = 0 - - diff --git a/main.py b/main.py index e86710f6..b2f1e49f 100644 --- a/main.py +++ b/main.py @@ -10,7 +10,8 @@ Created on Tue Dec 22 16:58:45 2020 import socketserver import argparse import logging - +import threading +import pyaudio #import tnc import static @@ -18,14 +19,50 @@ import helpers + +def start_cmd_socket(): + + try: + logging.info("SRV | STARTING TCP/IP CMD ON PORT: " + str(static.PORT)) + socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 + cmdserver = socketserver.TCPServer((static.HOST, static.PORT), tnc.CMDTCPRequestHandler) + cmdserver.serve_forever() + + finally: + cmdserver.server_close() + + +def start_data_socket(): + + try: + logging.info("SRV | STARTING TCP/IP DATA ON PORT: " + str(static.PORT + 1)) + socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 + dataserver = socketserver.TCPServer((static.HOST, static.PORT + 1), tnc.DATATCPRequestHandler) + dataserver.serve_forever() + + finally: + dataserver.server_close() + + + + +p = pyaudio.PyAudio() +devices = [] +for x in range(0, p.get_device_count()): + devices.append(f"{x} - {p.get_device_info_by_index(x)['name']}") + +for line in devices: + print(line) + + + + + if __name__ == '__main__': - - - static.MYCALLSIGN = b'DJ2LS' static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) @@ -61,14 +98,16 @@ if __name__ == '__main__': #-------------------------------------------- DEFINE LOGGING logging.basicConfig(format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', datefmt='%H:%M:%S', level=logging.INFO) - #logging.addLevelName(logging.INFO, "\033[1;37m%s\033[1;0m" % 'SUCCESS') - - logging.addLevelName( logging.DEBUG, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) - logging.addLevelName( logging.INFO, "\033[1;32m%s\033[1;0m" % logging.getLevelName(logging.INFO)) + logging.addLevelName( logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) + logging.addLevelName( logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO)) logging.addLevelName( logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) - logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) + logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % "FAILED") + #logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) logging.addLevelName( logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL)) + logging.addLevelName( 25, "\033[1;32m%s\033[1;0m" % "SUCCESS") + logging.addLevelName( 24, "\033[1;34m%s\033[1;0m" % "DATA") + # https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output #'DEBUG' : 37, # white @@ -78,13 +117,14 @@ if __name__ == '__main__': #'CRITICAL': 41, # white on red bg - #--------------------------------------------START CMD SERVER - logging.info("SRV | STARTING TCP/IP SOCKET ON PORT " + str(static.PORT)) - try: - socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 - server = socketserver.TCPServer((static.HOST, static.PORT), tnc.TCPRequestHandler) - server.serve_forever() - finally: - server.server_close() + + #--------------------------------------------START CMD & DATA SERVER + + cmd_server_thread = threading.Thread(target=start_cmd_socket, name="cmd server") + cmd_server_thread.start() + + data_server_thread = threading.Thread(target=start_data_socket, name="data server") + data_server_thread.start() + diff --git a/modem.py b/modem.py index 6a9dd11c..38ae7585 100644 --- a/modem.py +++ b/modem.py @@ -19,6 +19,8 @@ import helpers import static import arq +import audioop + @@ -94,15 +96,13 @@ class RF(): logging.debug("SEND SIGNALLING FRAME " + str(ack_buffer)) self.stream_tx.write(bytes(txbuffer)) - self.stream_tx.write(bytes(txbuffer)) - - static.ARQ_STATE = 'RECEIVING_DATA' #-------------------------------------------------------------------------------------------------------- # GET ARQ BURST FRAME VOM BUFFER AND MODULATE IT def transmit_arq_burst(self): + static.ARQ_STATE = 'SENDING_DATA' self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) @@ -186,6 +186,8 @@ class RF(): static.MYCALLSIGN_CRC8 + \ payload_data + #print(arqframe) + buffer = bytearray(static.FREEDV_DATA_PAYLOAD_PER_FRAME) # create TX buffer buffer[:len(arqframe)] = arqframe # set buffersize to length of data which will be send @@ -238,18 +240,18 @@ class RF(): time.sleep(0.01) 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) + #print(audioop.rms(data_in, 2)) data_in = data_in.rstrip(b'\x00') #print(data_in) - 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 logging.debug(self.c_lib.freedv_get_rx_status(freedv_data)) - #-------------STUCK IN SYNC DETECTOR stuck_in_sync_counter += 1 if self.c_lib.freedv_get_rx_status(freedv_data) == 10: @@ -285,11 +287,11 @@ class RF(): frametype = int.from_bytes(bytes(data_bytes_out[:1]), "big") frame = frametype - 10 n_frames_per_burst = int.from_bytes(bytes(data_bytes_out[1:2]), "big") - + if 50 >= frametype >= 10: if frame != 3 or force == True: arq.data_received(bytes(data_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") @@ -313,12 +315,12 @@ class RF(): time.sleep(0.01) nin = self.c_lib.freedv_nin(freedv_signalling) - 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 = data_in.rstrip(b'\x00') - self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), signalling_bytes_out, data_in] # check if really neccessary + #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------------------------ @@ -348,7 +350,6 @@ class RF(): rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) logging.debug("ACK-" + str(rxstatus)) - #print(rxstatus) if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10: self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC From 1969349b504c6559535da0b6ad48e6fecd692015 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:23:57 +0100 Subject: [PATCH 11/14] code cleanup --- arq.py | 47 ++++-------------------------- helpers.py | 34 +++++++++++++++++++++- main.py | 52 +++++++++++---------------------- modem.py | 5 ++-- sock.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ static.py | 43 +++++++++++----------------- 6 files changed, 158 insertions(+), 107 deletions(-) create mode 100644 sock.py diff --git a/arq.py b/arq.py index 4855155e..74bb96c8 100644 --- a/arq.py +++ b/arq.py @@ -13,36 +13,18 @@ from random import randrange import static import modem +modem = modem.RF() import helpers -#import tnc - - - - -modem = modem.RF() - -static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 3 #6?! -static.ARQ_ACK_PAYLOAD_PER_FRAME = 14 - 2# def data_received(data_in): - -# arqframe = frame_type + \ # 1 [:1] # frame type and current number of arq frame of (current) burst -# bytes([static.ARQ_TX_N_FRAMES_PER_BURST]) + \ # 1 [1:2] # total number of arq frames per (current) burst -# static.ARQ_N_CURRENT_ARQ_FRAME + \ # 2 [2:4] # current arq frame number -# static.ARQ_N_TOTAL_ARQ_FRAMES + \ # 2 [4:6] # total number arq frames -# static.ARQ_BURST_PAYLOAD_CRC + \ # 2 [6:8] # arq crc -# payload_data # N [8:N] # payload data - - static.ARQ_N_FRAME = int.from_bytes(bytes(data_in[:1]), "big") - 10 #get number of burst frame static.ARQ_N_RX_FRAMES_PER_BURSTS = int.from_bytes(bytes(data_in[1:2]), "big") #get number of bursts from received frame static.ARQ_RX_N_CURRENT_ARQ_FRAME = int.from_bytes(bytes(data_in[2:4]), "big") #get current number of total frames static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = int.from_bytes(bytes(data_in[4:6]), "big") # get get total number of frames - static.ARQ_BURST_PAYLOAD_CRC = data_in[6:8] logging.debug("----------------------------------------------------------------") @@ -50,7 +32,6 @@ def data_received(data_in): logging.debug("ARQ_N_RX_FRAMES_PER_BURSTS: " + str(static.ARQ_N_RX_FRAMES_PER_BURSTS)) logging.debug("ARQ_RX_N_CURRENT_ARQ_FRAME: " + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME)) logging.debug("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME: " + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME)) - logging.debug("static.ARQ_BURST_PAYLOAD_CRC: " + str(static.ARQ_BURST_PAYLOAD_CRC)) logging.debug("----------------------------------------------------------------") @@ -63,7 +44,6 @@ def data_received(data_in): #allocate ARQ_RX_FRAME_BUFFER as a list with "None" if not already done. This should be done only once per burst! # here we will save the N frame of a data frame to N list position so we can explicit search for it - # delete frame buffer if first frame to make sure the buffer is cleared and no junks of a old frame is remaining if static.ARQ_RX_N_CURRENT_ARQ_FRAME == 1: static.ARQ_RX_FRAME_BUFFER = [] @@ -93,11 +73,8 @@ def data_received(data_in): static.ARQ_RX_BURST_BUFFER[static.ARQ_N_FRAME] = bytes(data_in) - #for i in range(len(static.ARQ_RX_BURST_BUFFER)): - # print(static.ARQ_RX_BURST_BUFFER[i]) - -# - ------------------------- ARQ BURST CHECKER - + +# - ------------------------- ARQ BURST CHECKER # run only if we recieved all ARQ FRAMES per ARQ BURST if static.ARQ_RX_BURST_BUFFER.count(None) == 1: #count nones logging.info("ARQ | TX | BURST ACK") @@ -116,7 +93,6 @@ def data_received(data_in): elif static.ARQ_N_FRAME == static.ARQ_N_RX_FRAMES_PER_BURSTS and static.ARQ_RX_BURST_BUFFER.count(None) != 1: # --------------- CHECK WHICH BURST FRAMES WE ARE MISSING ------------------------------------------- - missing_frames = b'' for burstnumber in range(1,len(static.ARQ_RX_BURST_BUFFER)): @@ -140,9 +116,7 @@ def data_received(data_in): modem.transmit_arq_ack(rpt_frame) - # ---------------------------- FRAME MACHINE - # --------------- IF LIST NOT CONTAINS "None" stick everything together complete_data_frame = bytearray() #print("static.ARQ_RX_FRAME_BUFFER.count(None)" + str(static.ARQ_RX_FRAME_BUFFER.count(None))) @@ -203,7 +177,6 @@ def data_received(data_in): #print("----------------------------------------------------------------") #print(static.RX_BUFFER[-1]) - #tnc.request.sendall(bytes(static.RX_BUFFER[-1])) #print("----------------------------------------------------------------") else: @@ -215,8 +188,8 @@ def data_received(data_in): def transmit(data_out): - static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 8 #3 ohne ARQ_TX_N_FRAMES_PER_BURST - frame_header_length = 4 + 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) @@ -367,8 +340,7 @@ def transmit(data_out): logging.debug("static.ARQ_N_SENT_FRAMES " + str(static.ARQ_N_SENT_FRAMES)) logging.debug("static.TX_BUFFER_SIZE " + str(static.TX_BUFFER_SIZE)) logging.debug("static.TX_N_RETRIES " + str(static.TX_N_RETRIES)) - logging.debug("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) - + logging.debug("static.TX_N_MAX_RETRIES " + str(static.TX_N_MAX_RETRIES)) logging.debug("static.ARQ_STATE " + str(static.ARQ_STATE)) logging.debug("static.ARQ_FRAME_ACK_RECEIVED " + str(static.ARQ_FRAME_ACK_RECEIVED)) logging.debug("static.ARQ_RX_FRAME_TIMEOUT " + str(static.ARQ_RX_FRAME_TIMEOUT)) @@ -419,12 +391,8 @@ def transmit(data_out): - - - # BURST MACHINE TO DEFINE N BURSTS PER FRAME ---> LATER WE CAN USE CHANNEL MESSUREMENT TO SET FRAMES PER BURST def get_n_frames_per_burst(): - #n_frames_per_burst = randrange(1,10) n_frames_per_burst = 2 return n_frames_per_burst @@ -432,19 +400,16 @@ def get_n_frames_per_burst(): def burst_ack_received(): - static.ARQ_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame def frame_ack_received(): - static.ARQ_FRAME_ACK_RECEIVED = True #Force data loops of TNC to stop and continue with next frame def burst_rpt_received(data_in): - static.ARQ_RPT_RECEIVED = True static.ARQ_RPT_FRAMES = [] diff --git a/helpers.py b/helpers.py index d821851a..54fae9e0 100644 --- a/helpers.py +++ b/helpers.py @@ -9,8 +9,8 @@ Created on Fri Dec 25 21:25:14 2020 import time import threading import logging -from colorlog import ColoredFormatter import crcengine +import pyaudio import static @@ -62,4 +62,36 @@ def arq_reset_frame_machine(): static.ARQ_N_SENT_FRAMES = 0 static.ARQ_TX_N_FRAMES_PER_BURST = 0 + +def setup_logging(): + + logging.basicConfig(format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', datefmt='%H:%M:%S', level=logging.INFO) + logging.addLevelName( logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) + logging.addLevelName( logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO)) + logging.addLevelName( logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) + logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % "FAILED") + #logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) + logging.addLevelName( logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL)) + + logging.addLevelName( 25, "\033[1;32m%s\033[1;0m" % "SUCCESS") + logging.addLevelName( 24, "\033[1;34m%s\033[1;0m" % "DATA") + + + # https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output + #'DEBUG' : 37, # white + #'INFO' : 36, # cyan + #'WARNING' : 33, # yellow + #'ERROR' : 31, # red + #'CRITICAL': 41, # white on red bg + + + +def list_audio_devices(): + p = pyaudio.PyAudio() + devices = [] + for x in range(0, p.get_device_count()): + devices.append(f"{x} - {p.get_device_info_by_index(x)['name']}") + + for line in devices: + print(line) diff --git a/main.py b/main.py index b2f1e49f..6361a702 100644 --- a/main.py +++ b/main.py @@ -11,24 +11,18 @@ import socketserver import argparse import logging import threading -import pyaudio -#import tnc import static import helpers - - - - def start_cmd_socket(): try: logging.info("SRV | STARTING TCP/IP CMD ON PORT: " + str(static.PORT)) socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 - cmdserver = socketserver.TCPServer((static.HOST, static.PORT), tnc.CMDTCPRequestHandler) + cmdserver = socketserver.TCPServer((static.HOST, static.PORT), sock.CMDTCPRequestHandler) cmdserver.serve_forever() finally: @@ -40,22 +34,19 @@ def start_data_socket(): try: logging.info("SRV | STARTING TCP/IP DATA ON PORT: " + str(static.PORT + 1)) socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 - dataserver = socketserver.TCPServer((static.HOST, static.PORT + 1), tnc.DATATCPRequestHandler) + dataserver = socketserver.TCPServer((static.HOST, static.PORT + 1), sock.DATATCPRequestHandler) dataserver.serve_forever() finally: - dataserver.server_close() + dataserver.server_close() + + + + -p = pyaudio.PyAudio() -devices = [] -for x in range(0, p.get_device_count()): - devices.append(f"{x} - {p.get_device_info_by_index(x)['name']}") - -for line in devices: - print(line) @@ -63,6 +54,14 @@ for line in devices: if __name__ == '__main__': + # config logging + helpers.setup_logging() + + # list audio devices + helpers.list_audio_devices() + + + static.MYCALLSIGN = b'DJ2LS' static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) @@ -93,28 +92,9 @@ if __name__ == '__main__': static.AUDIO_OUTPUT_DEVICE = args.audio_output_device static.PORT = args.socket_port - import tnc # we need to wait until we got all parameters from argparse - - #-------------------------------------------- DEFINE LOGGING - logging.basicConfig(format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', datefmt='%H:%M:%S', level=logging.INFO) - - logging.addLevelName( logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) - logging.addLevelName( logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO)) - logging.addLevelName( logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) - logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % "FAILED") - #logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) - logging.addLevelName( logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL)) - - logging.addLevelName( 25, "\033[1;32m%s\033[1;0m" % "SUCCESS") - logging.addLevelName( 24, "\033[1;34m%s\033[1;0m" % "DATA") + import sock # we need to wait until we got all parameters from argparse - # https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output - #'DEBUG' : 37, # white - #'INFO' : 36, # cyan - #'WARNING' : 33, # yellow - #'ERROR' : 31, # red - #'CRITICAL': 41, # white on red bg diff --git a/modem.py b/modem.py index 38ae7585..6579f012 100644 --- a/modem.py +++ b/modem.py @@ -10,7 +10,8 @@ import ctypes from ctypes import * import pathlib import pyaudio -import sys +import audioop +#import sys import logging import time import threading @@ -19,7 +20,7 @@ import helpers import static import arq -import audioop + diff --git a/sock.py b/sock.py new file mode 100644 index 00000000..f5eb3895 --- /dev/null +++ b/sock.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Dec 25 21:25:14 2020 + +@author: DJ2LS +""" + +import socketserver +import threading +import logging + + +import static +import arq + +class DATATCPRequestHandler(socketserver.BaseRequestHandler): + + def handle(self): + + self.data = bytes() + while True: + chunk = self.request.recv(8192)#.strip() + self.data += chunk + if chunk.endswith(b'\n'): + break + + + +class CMDTCPRequestHandler(socketserver.BaseRequestHandler): + + def handle(self): + + self.data = bytes() + while True: + chunk = self.request.recv(8192)#.strip() + self.data += chunk + if chunk.endswith(b'\n'): + break + + + + # self.request is the TCP socket connected to the client + #self.data = self.request.recv(1024).strip() +### self.data = self.request.recv(1000000).strip() + + # interrupt listening loop "while true" by setting MODEM_RECEIVE to False + #if len(self.data) > 0: + # static.MODEM_RECEIVE = False + + + ####print("{} wrote:".format(self.client_address[0])) + ####print(self.data) + + # just send back the same data, but upper-cased + #####self.request.sendall(self.data.upper()) + + #if self.data == b'TEST': + #logging.info("DER TEST KLAPPT! HIER KOMMT DER COMMAND PARSER HIN!") + if self.data.startswith(b'SHOWBUFFERSIZE'): + self.request.sendall(bytes(static.RX_BUFFER[-1])) + print(static.RX_BUFFER_SIZE) + +# BROADCAST PARSER ----------------------------------------------------------- + + if self.data.startswith(b'BC:'): + #import modem + #modem = modem.RF() + + data = self.data.split(b'BC:') + #modem.Transmit(data[1]) + + + +# SEND AN ARQ FRAME ----------------------------------------------------------- + + if self.data.startswith(b'ARQ:'): + + data = self.data.split(b'ARQ:') + data_out = data[1] + + TRANSMIT_ARQ = threading.Thread(target=arq.transmit, args=[data_out], name="TRANSMIT_ARQ") + TRANSMIT_ARQ.start() + diff --git a/static.py b/static.py index 4fa71047..f1613d74 100644 --- a/static.py +++ b/static.py @@ -5,23 +5,21 @@ Created on Wed Dec 23 11:13:57 2020 @author: DJ2LS """ -# ADDITION MESSUREMENT: -#AUDIO TIME: 7.451462268829346 #12 # 1 FRAME + PREAMBLE -#MODULATION TIME: 0.002051115036010742 #12 # 1 FRAME + PREAMBLE - -#MODULATION TIME: 0.004580974578857422 #12 # 2 FRAME + PREAMBLE -#AUDIO TIME: 14.750595331192017 #12 # 2 FRAME + PREAMBLE - +# Operator Defaults MYCALLSIGN = b'' MYCALLSIGN_CRC8 = b'' DXCALLSIGN = b'' DXCALLSIGN_CRC8 = b'' +MYGRID = b'' +#--------------------------------- - - +# Server Defaults +HOST = "localhost" +PORT = 3000 +#--------------------------------- # FreeDV Defaults FREEDV_RECEIVE = True @@ -33,13 +31,9 @@ FREEDV_DATA_BYTES_PER_FRAME = 0 FREEDV_DATA_PAYLOAD_PER_FRAME = 0 FREEDV_SIGNALLING_BYTES_PER_FRAME = 0 FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = 0 +#--------------------------------- -# Server Defaults -HOST = "localhost" -PORT = 3000 - - -#AUdio Defaults +#Audio Defaults AUDIO_INPUT_DEVICE = 1 AUDIO_OUTPUT_DEVICE = 1 #TX_SAMPLE_STATE = None @@ -50,20 +44,17 @@ AUDIO_OUTPUT_DEVICE = 1 MODEM_SAMPLE_RATE = 8000 #8000 AUDIO_FRAMES_PER_BUFFER = 2048 AUDIO_CHANNELS = 1 +#--------------------------------- - -#TNC DEFAULTS -# ARQ -TX_N_MAX_RETRIES = 3 +#ARQ DEFAULTS +TX_N_MAX_RETRIES = 10 TX_N_RETRIES = 0 - - ARQ_TX_N_FRAMES_PER_BURST = 0 ARQ_TX_N_BURSTS = 0 ARQ_PAYLOAD_PER_FRAME = 0 -ARQ_ACK_WAITING_FOR_ID = 0 + ARQ_RX_BURST_BUFFER = [] ARQ_RX_FRAME_BUFFER = [] ARQ_RX_FRAME_N_BURSTS = 0 @@ -79,22 +70,20 @@ ARQ_RX_N_CURRENT_ARQ_FRAME = 0 ## ARQ_N_RX_ARQ_FRAMES = 0 # total number of received frames - ARQ_N_RX_FRAMES_PER_BURSTS = 0 # NUMBER OF FRAMES WE ARE WAITING FOR --> GOT DATA FROM RECEIVED FRAME ARQ_ACK_PAYLOAD_PER_FRAME = 0 # PAYLOAD per ACK frame ARQ_ACK_RECEIVED = False # set to 1 if ACK received ARQ_RX_ACK_TIMEOUT = False # set to 1 if timeut reached -ARQ_RX_ACK_TIMEOUT_SECONDS = 5.0 #timeout for waiting for ACK frames - +ARQ_RX_ACK_TIMEOUT_SECONDS = 10.0 #timeout for waiting for ACK frames ARQ_FRAME_ACK_RECEIVED = False # set to 1 if FRAME ACK received ARQ_RX_FRAME_TIMEOUT = False -ARQ_RX_FRAME_TIMEOUT_SECONDS = 5.0 +ARQ_RX_FRAME_TIMEOUT_SECONDS = 10.0 ARQ_RX_RPT_TIMEOUT = False -ARQ_RX_RPT_TIMEOUT_SECONDS = 5.0 +ARQ_RX_RPT_TIMEOUT_SECONDS = 10.0 ARQ_RPT_RECEIVED = False #indicate if RPT frame has been received ARQ_RPT_FRAMES = [] #buffer for frames which are requested to repeat From a5d0e6e60814f7d4ec6462997cbf73cc522799f8 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:24:36 +0100 Subject: [PATCH 12/14] switch to sock file --- tnc.py | 76 ---------------------------------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 tnc.py diff --git a/tnc.py b/tnc.py deleted file mode 100644 index f0785dd4..00000000 --- a/tnc.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Created on Fri Dec 25 21:25:14 2020 - -@author: DJ2LS -""" - -import socketserver -import threading -import logging - - -import static -import arq - - - -class TCPRequestHandler(socketserver.BaseRequestHandler): - - def handle(self): - - self.data = bytes() - while True: - chunk = self.request.recv(8192)#.strip() - if chunk.endswith(b'\n'): - break - - self.data += chunk - - - # self.request is the TCP socket connected to the client - #self.data = self.request.recv(1024).strip() -### self.data = self.request.recv(1000000).strip() - - # interrupt listening loop "while true" by setting MODEM_RECEIVE to False - #if len(self.data) > 0: - # static.MODEM_RECEIVE = False - - - ####print("{} wrote:".format(self.client_address[0])) - ####print(self.data) - - # just send back the same data, but upper-cased - #####self.request.sendall(self.data.upper()) - - #if self.data == b'TEST': - #logging.info("DER TEST KLAPPT! HIER KOMMT DER COMMAND PARSER HIN!") - if self.data.startswith(b'SHOWBUFFERSIZE'): - self.request.sendall(bytes(static.RX_BUFFER[-1])) - print(static.RX_BUFFER_SIZE) - -# BROADCAST PARSER ----------------------------------------------------------- - - if self.data.startswith(b'BC:'): - #import modem - #modem = modem.RF() - - data = self.data.split(b'BC:') - #modem.Transmit(data[1]) - - - -# SEND AN ARQ FRAME ----------------------------------------------------------- - - if self.data.startswith(b'ARQ:'): - - data = self.data.split(b'ARQ:') - data_out = data[1] - - #arq.transmit(data_out) - - TRANSMIT_ARQ = threading.Thread(target=arq.transmit, args=[data_out], name="TRANSMIT_ARQ") - TRANSMIT_ARQ.start() - - From 4e3d2cc158445873e59d08b42706127a6e24797c Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:36:01 +0100 Subject: [PATCH 13/14] cleanup & optimized data/cmd socket --- modem.py | 15 +++++++-------- sock.py | 51 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/modem.py b/modem.py index 6579f012..2dcdbd3e 100644 --- a/modem.py +++ b/modem.py @@ -259,17 +259,16 @@ class RF(): stuck_in_sync_10_counter += 1 - #print(stuck_in_sync_counter) - #if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv_data) == 10: - # print("stuck in sync #1 --> DOING UNSYNC") - # self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC - # stuck_in_sync_counter = 0 - # stuck_in_sync_10_counter = 0 - # data_in = None + if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv_data) == 10: + logging.critical("stuck in sync #1") + self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC + stuck_in_sync_counter = 0 + stuck_in_sync_10_counter = 0 + data_in = None if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2: - logging.critical("modem stuck in sync") + logging.critical("stuck in sync #2") self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC stuck_in_sync_counter = 0 stuck_in_sync_10_counter = 0 diff --git a/sock.py b/sock.py index f5eb3895..ebbc18f0 100644 --- a/sock.py +++ b/sock.py @@ -24,6 +24,15 @@ class DATATCPRequestHandler(socketserver.BaseRequestHandler): self.data += chunk if chunk.endswith(b'\n'): break + + # SEND AN ARQ FRAME ------------------------- + if self.data.startswith(b'ARQ:'): + + data = self.data.split(b'ARQ:') + data_out = data[1] + + TRANSMIT_ARQ = threading.Thread(target=arq.transmit, args=[data_out], name="TRANSMIT_ARQ") + TRANSMIT_ARQ.start() @@ -60,25 +69,29 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): if self.data.startswith(b'SHOWBUFFERSIZE'): self.request.sendall(bytes(static.RX_BUFFER[-1])) print(static.RX_BUFFER_SIZE) - -# BROADCAST PARSER ----------------------------------------------------------- - if self.data.startswith(b'BC:'): - #import modem - #modem = modem.RF() - - data = self.data.split(b'BC:') - #modem.Transmit(data[1]) - - - -# SEND AN ARQ FRAME ----------------------------------------------------------- - if self.data.startswith(b'ARQ:'): - data = self.data.split(b'ARQ:') - data_out = data[1] - - TRANSMIT_ARQ = threading.Thread(target=arq.transmit, args=[data_out], name="TRANSMIT_ARQ") - TRANSMIT_ARQ.start() - + +def start_cmd_socket(): + + try: + logging.info("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(static.PORT)) + socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 + cmdserver = socketserver.TCPServer((static.HOST, static.PORT), CMDTCPRequestHandler) + cmdserver.serve_forever() + + finally: + cmdserver.server_close() + + +def start_data_socket(): + + try: + logging.info("SRV | STARTING TCP/IP SOCKET FOR DATA ON PORT: " + str(static.PORT + 1)) + socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 + dataserver = socketserver.TCPServer((static.HOST, static.PORT + 1), DATATCPRequestHandler) + dataserver.serve_forever() + + finally: + dataserver.server_close() From 829692a13d2dcfcbc1c0377099e53c80a8290fe7 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:36:26 +0100 Subject: [PATCH 14/14] cleanup --- main.py | 50 ++++---------------------------------------------- 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/main.py b/main.py index 6361a702..b6b19c85 100644 --- a/main.py +++ b/main.py @@ -14,43 +14,7 @@ import threading import static import helpers - - - -def start_cmd_socket(): - - try: - logging.info("SRV | STARTING TCP/IP CMD ON PORT: " + str(static.PORT)) - socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 - cmdserver = socketserver.TCPServer((static.HOST, static.PORT), sock.CMDTCPRequestHandler) - cmdserver.serve_forever() - - finally: - cmdserver.server_close() - - -def start_data_socket(): - - try: - logging.info("SRV | STARTING TCP/IP DATA ON PORT: " + str(static.PORT + 1)) - socketserver.TCPServer.allow_reuse_address = True #https://stackoverflow.com/a/16641793 - dataserver = socketserver.TCPServer((static.HOST, static.PORT + 1), sock.DATATCPRequestHandler) - dataserver.serve_forever() - - finally: - dataserver.server_close() - - - - - - - - - - - - + if __name__ == '__main__': @@ -86,24 +50,18 @@ if __name__ == '__main__': args = parser.parse_args() - + #--------------------------------------------START CMD & DATA SERVER static.FREEDV_DATA_MODE = args.freedv_data_mode static.AUDIO_INPUT_DEVICE = args.audio_input_device static.AUDIO_OUTPUT_DEVICE = args.audio_output_device static.PORT = args.socket_port import sock # we need to wait until we got all parameters from argparse - - - - - - #--------------------------------------------START CMD & DATA SERVER - cmd_server_thread = threading.Thread(target=start_cmd_socket, name="cmd server") + cmd_server_thread = threading.Thread(target=sock.start_cmd_socket, name="cmd server") cmd_server_thread.start() - data_server_thread = threading.Thread(target=start_data_socket, name="data server") + data_server_thread = threading.Thread(target=sock.start_data_socket, name="data server") data_server_thread.start()