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
This commit is contained in:
DJ2LS 2021-02-08 16:33:11 +01:00 committed by GitHub
parent 2fd8f5f6f7
commit 06cb35276e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 78 deletions

142
arq.py
View file

@ -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

View file

@ -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)))

View file

@ -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