From 4a239843608e59d1dcb86b887dccdfadd67a0dd7 Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Tue, 21 Jun 2022 18:47:18 -0400 Subject: [PATCH 1/5] Remove allmodes (255) option from TNC. First attempt. --- tnc/codec2.py | 1 - tnc/data_handler.py | 37 +++---------------------------------- 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/tnc/codec2.py b/tnc/codec2.py index 7cbbe581..b6c83b0b 100644 --- a/tnc/codec2.py +++ b/tnc/codec2.py @@ -24,7 +24,6 @@ class FREEDV_MODE(Enum): Enumeration for codec2 modes and names """ - allmodes = 255 datac0 = 14 datac1 = 10 datac3 = 12 diff --git a/tnc/data_handler.py b/tnc/data_handler.py index c6a8dd04..2357cf0e 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -876,39 +876,8 @@ class DATA: while not self.data_frame_ack_received and static.ARQ_STATE: # we have TX_N_MAX_RETRIES_PER_BURST attempts for sending a burst for self.tx_n_retry_of_burst in range(TX_N_MAX_RETRIES_PER_BURST): - # AUTO MODE SELECTION - # mode 255 == AUTO MODE - # force usage of selected mode - if mode != 255: - data_mode = mode - self.log.debug("[TNC] FIXED MODE:", mode=data_mode) - else: - # we are doing a modulo check of transmission retries of the actual burst - # every 2nd retry which fails, decreases speedlevel by 1. - # as soon as we received an ACK for the current burst, speed_level will increase - # by 1. - # The intent is to optimize speed by adapting to the current RF conditions. - # if not self.tx_n_retry_of_burst % 2 and self.tx_n_retry_of_burst > 0: - # self.speed_level = max(self.speed_level - 1, 0) - - # if self.tx_n_retry_of_burst <= 1: - # self.speed_level += 1 - # self.speed_level = max(self.speed_level + 1, len(self.mode_list) - 1) - - # Bound speed level to: - # - minimum of either the speed or the length of mode list - 1 - # - maximum of either the speed or zero - self.speed_level = min(self.speed_level, len(self.mode_list) - 1) - self.speed_level = max(self.speed_level, 0) - static.ARQ_SPEED_LEVEL = self.speed_level - data_mode = self.mode_list[self.speed_level] - - self.log.debug( - "[TNC] Speed-level:", - level=self.speed_level, - retry=self.tx_n_retry_of_burst, - mode=data_mode, - ) + data_mode = mode + self.log.debug("[TNC] FIXED MODE:", mode=data_mode) # Payload information payload_per_frame = modem.get_bytes_per_frame(data_mode) - 2 @@ -2407,7 +2376,7 @@ class DATA: elif mode == codec2.FREEDV_MODE.fsk_ldpc_1.value: modem.RECEIVE_FSK_LDPC_1 = True self.log.debug("[TNC] Changing listening data mode", mode="fsk_ldpc_1") - elif mode == codec2.FREEDV_MODE.allmodes.value: + else: modem.RECEIVE_DATAC1 = True modem.RECEIVE_DATAC3 = True modem.RECEIVE_FSK_LDPC_1 = True From 9de09c8f9a6a0b056c08607037b6f4475b10d16a Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Tue, 21 Jun 2022 19:46:22 -0400 Subject: [PATCH 2/5] Add datac0 negative tests to cmake --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index de294c38..7ebb9727 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,13 @@ add_test(NAME datac0_frames python3 test_datac0.py") set_tests_properties(datac0_frames PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0") +add_test(NAME datac0_frames_negative + COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; + export PYTHONPATH=../tnc; + cd ${CMAKE_CURRENT_SOURCE_DIR}/test; + python3 test_datac0_negative.py") + set_tests_properties(datac0_frames_negative PROPERTIES PASS_REGULAR_EXPRESSION "errors: 0") + add_test(NAME helper_routines COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src; export PYTHONPATH=../tnc; From 275e017a050aebd95e9750d0c7894e9b79b82ac4 Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Thu, 23 Jun 2022 18:16:32 -0400 Subject: [PATCH 3/5] Restore a section errantly removed. --- tnc/data_handler.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 2357cf0e..9842441b 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -879,6 +879,33 @@ class DATA: data_mode = mode self.log.debug("[TNC] FIXED MODE:", mode=data_mode) + # we are doing a modulo check of transmission retries of the actual burst + # every 2nd retry which fails, decreases speedlevel by 1. + # as soon as we received an ACK for the current burst, speed_level will increase + # by 1. + # The intent is to optimize speed by adapting to the current RF conditions. + # if not self.tx_n_retry_of_burst % 2 and self.tx_n_retry_of_burst > 0: + # self.speed_level = max(self.speed_level - 1, 0) + + # if self.tx_n_retry_of_burst <= 1: + # self.speed_level += 1 + # self.speed_level = max(self.speed_level + 1, len(self.mode_list) - 1) + + # Bound speed level to: + # - minimum of either the speed or the length of mode list - 1 + # - maximum of either the speed or zero + self.speed_level = min(self.speed_level, len(self.mode_list) - 1) + self.speed_level = max(self.speed_level, 0) + static.ARQ_SPEED_LEVEL = self.speed_level + data_mode = self.mode_list[self.speed_level] + + self.log.debug( + "[TNC] Speed-level:", + level=self.speed_level, + retry=self.tx_n_retry_of_burst, + mode=data_mode, + ) + # Payload information payload_per_frame = modem.get_bytes_per_frame(data_mode) - 2 From d16e98f4cd77cc6b9a8e164a234f19dcb8842f6a Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Fri, 24 Jun 2022 09:22:46 -0400 Subject: [PATCH 4/5] Remove datac0 from high/low bandwidth mode lists. Datac0 causes frame CRC errors, removing from mode lists. Shorten codec2.FREEDV_MODE by import alias. Use FREEDV_MODE enum in logs for easier debugging. Minor reformatting. --- tnc/data_handler.py | 89 ++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 9842441b..965d5ccc 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -25,6 +25,7 @@ import static import structlog import ujson as json from exceptions import NoCallsign +from codec2 import FREEDV_MODE TESTMODE = False @@ -84,17 +85,15 @@ class DATA: # List of codec2 modes to use in "low bandwidth" mode. self.mode_list_low_bw = [ - codec2.FREEDV_MODE.datac0.value, - codec2.FREEDV_MODE.datac3.value, + FREEDV_MODE.datac3.value, ] # List for time to wait for corresponding mode in seconds self.time_list_low_bw = [3, 7] # List of codec2 modes to use in "high bandwidth" mode. self.mode_list_high_bw = [ - codec2.FREEDV_MODE.datac0.value, - codec2.FREEDV_MODE.datac3.value, - codec2.FREEDV_MODE.datac1.value, + FREEDV_MODE.datac3.value, + FREEDV_MODE.datac1.value, ] # List for time to wait for corresponding mode in seconds self.time_list_high_bw = [3, 7, 8, 30] @@ -360,7 +359,7 @@ class DATA: def enqueue_frame_for_tx( self, frame_to_tx: bytearray, - c2_mode=codec2.FREEDV_MODE.datac0.value, + c2_mode=FREEDV_MODE.datac0.value, copies=1, repeat_delay=0, ) -> None: @@ -376,7 +375,7 @@ class DATA: :param repeat_delay: Delay time before sending repeat frame, defaults to 0 :type repeat_delay: int, optional """ - self.log.debug("[TNC] enqueue_frame_for_tx", c2_mode=c2_mode) + self.log.debug("[TNC] enqueue_frame_for_tx", c2_mode=FREEDV_MODE(c2_mode).name) # Set the TRANSMITTING flag before adding an object to the transmit queue # TODO: This is not that nice, we could improve this somehow @@ -676,7 +675,7 @@ class DATA: if bof_position >= 0: payload = static.RX_FRAME_BUFFER[ - bof_position + len(self.data_frame_bof): eof_position + bof_position + len(self.data_frame_bof) : eof_position ] frame_length = int.from_bytes(payload[4:8], "big") # 4:8 4bytes static.TOTAL_BYTES = frame_length @@ -703,7 +702,7 @@ class DATA: # Extract raw data from buffer payload = static.RX_FRAME_BUFFER[ - bof_position + len(self.data_frame_bof): eof_position + bof_position + len(self.data_frame_bof) : eof_position ] # Get the data frame crc data_frame_crc = payload[:4] # 0:4 = 4 bytes @@ -741,7 +740,13 @@ class DATA: # Re-code data_frame in base64, UTF-8 for JSON UI communication. base64_data = base64.b64encode(data_frame).decode("UTF-8") static.RX_BUFFER.append( - [self.transmission_uuid, timestamp, static.DXCALLSIGN, static.DXGRID, base64_data] + [ + self.transmission_uuid, + timestamp, + static.DXCALLSIGN, + static.DXGRID, + base64_data, + ] ) self.send_data_to_socket_queue( freedata="tnc-message", @@ -787,8 +792,8 @@ class DATA: self.log.warning( "[TNC] ARQ | RX | DATA FRAME NOT SUCCESSFULLY RECEIVED!", e="wrong crc", - expected=data_frame_crc, - received=data_frame_crc_received, + expected=data_frame_crc.hex(), + received=data_frame_crc_received.hex(), overflows=static.BUFFER_OVERFLOW_COUNTER, ) @@ -841,7 +846,11 @@ class DATA: bytesperminute=static.ARQ_BYTES_PER_MINUTE, ) - self.log.info("[TNC] | TX | DATACHANNEL", mode=mode, Bytes=static.TOTAL_BYTES) + self.log.info( + "[TNC] | TX | DATACHANNEL", + mode=FREEDV_MODE(mode).name, + Bytes=static.TOTAL_BYTES, + ) # Compress data frame data_frame_compressed = zlib.compress(data_out) @@ -857,7 +866,7 @@ class DATA: # Append a crc at the beginning and end of file indicators frame_payload_crc = helpers.get_crc_32(data_out) - self.log.debug("[TNC] frame payload CRC:", crc=frame_payload_crc) + self.log.debug("[TNC] frame payload CRC:", crc=frame_payload_crc.hex()) # Assemble the data frame data_out = ( @@ -877,7 +886,7 @@ class DATA: # we have TX_N_MAX_RETRIES_PER_BURST attempts for sending a burst for self.tx_n_retry_of_burst in range(TX_N_MAX_RETRIES_PER_BURST): data_mode = mode - self.log.debug("[TNC] FIXED MODE:", mode=data_mode) + self.log.debug("[TNC] FIXED MODE:", mode=FREEDV_MODE(data_mode).name) # we are doing a modulo check of transmission retries of the actual burst # every 2nd retry which fails, decreases speedlevel by 1. @@ -903,7 +912,7 @@ class DATA: "[TNC] Speed-level:", level=self.speed_level, retry=self.tx_n_retry_of_burst, - mode=data_mode, + mode=FREEDV_MODE(data_mode).name, ) # Payload information @@ -943,7 +952,7 @@ class DATA: self.log.debug("[TNC] tempbuffer:", tempbuffer=tempbuffer) self.log.info( "[TNC] ARQ | TX | FRAMES", - mode=data_mode, + mode=FREEDV_MODE(data_mode).name, fpb=TX_N_FRAMES_PER_BURST, retry=self.tx_n_retry_of_burst, ) @@ -1111,7 +1120,11 @@ class DATA: self.burst_ack_snr = int.from_bytes(bytes(data_in[7:8]), "big") self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big") static.ARQ_SPEED_LEVEL = self.speed_level - self.log.debug("[TNC] burst_ack_received:", speed_level=self.speed_level) + self.log.debug( + "[TNC] burst_ack_received:", + speed_level=self.speed_level, + c2_mode=FREEDV_MODE(self.mode_list[self.speed_level]).name, + ) # Reset burst nack counter self.burst_nack_counter = 0 @@ -1149,7 +1162,11 @@ class DATA: self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big") static.ARQ_SPEED_LEVEL = self.speed_level self.burst_nack_counter += 1 - self.log.debug("[TNC] burst_nack_received:", speed_level=self.speed_level) + self.log.debug( + "[TNC] burst_nack_received:", + speed_level=self.speed_level, + c2_mode=FREEDV_MODE(self.mode_list[self.speed_level]).name, + ) def frame_ack_received(self): """Received an ACK for a transmitted frame""" @@ -1840,13 +1857,9 @@ class DATA: self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx( - ping_frame, c2_mode=codec2.FREEDV_MODE.fsk_ldpc_0.value - ) + self.enqueue_frame_for_tx(ping_frame, c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: - self.enqueue_frame_for_tx( - ping_frame, c2_mode=codec2.FREEDV_MODE.datac0.value - ) + self.enqueue_frame_for_tx(ping_frame, c2_mode=FREEDV_MODE.datac0.value) def received_ping(self, data_in: bytes) -> None: """ @@ -1875,7 +1888,7 @@ class DATA: mycallsign=str(self.mycallsign, "UTF-8"), dxcallsign=str(static.DXCALLSIGN, "UTF-8"), dxgrid=str(static.DXGRID, "UTF-8"), - snr=str(static.SNR) + snr=str(static.SNR), ) # check if callsign ssid override valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[1:4]) @@ -1901,13 +1914,9 @@ class DATA: self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx( - ping_frame, c2_mode=codec2.FREEDV_MODE.fsk_ldpc_0.value - ) + self.enqueue_frame_for_tx(ping_frame, c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: - self.enqueue_frame_for_tx( - ping_frame, c2_mode=codec2.FREEDV_MODE.datac0.value - ) + self.enqueue_frame_for_tx(ping_frame, c2_mode=FREEDV_MODE.datac0.value) def received_ping_ack(self, data_in: bytes) -> None: """ @@ -2026,7 +2035,7 @@ class DATA: if static.ENABLE_FSK: self.enqueue_frame_for_tx( beacon_frame, - c2_mode=codec2.FREEDV_MODE.fsk_ldpc_0.value, + c2_mode=FREEDV_MODE.fsk_ldpc_0.value, ) else: self.enqueue_frame_for_tx(beacon_frame) @@ -2104,9 +2113,7 @@ class DATA: self.log.debug("[TNC] CQ Frame:", data=[cq_frame]) if static.ENABLE_FSK: - self.enqueue_frame_for_tx( - cq_frame, c2_mode=codec2.FREEDV_MODE.fsk_ldpc_0.value - ) + self.enqueue_frame_for_tx(cq_frame, c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: self.enqueue_frame_for_tx(cq_frame) @@ -2176,9 +2183,7 @@ class DATA: self.log.info("[TNC] ENABLE FSK", state=static.ENABLE_FSK) if static.ENABLE_FSK: - self.enqueue_frame_for_tx( - qrv_frame, c2_mode=codec2.FREEDV_MODE.fsk_ldpc_0.value - ) + self.enqueue_frame_for_tx(qrv_frame, c2_mode=FREEDV_MODE.fsk_ldpc_0.value) else: self.enqueue_frame_for_tx(qrv_frame) @@ -2394,13 +2399,13 @@ class DATA: """ # set modes we want to listen to - if mode == codec2.FREEDV_MODE.datac1.value: + if mode == FREEDV_MODE.datac1.value: modem.RECEIVE_DATAC1 = True self.log.debug("[TNC] Changing listening data mode", mode="datac1") - elif mode == codec2.FREEDV_MODE.datac3.value: + elif mode == FREEDV_MODE.datac3.value: modem.RECEIVE_DATAC3 = True self.log.debug("[TNC] Changing listening data mode", mode="datac3") - elif mode == codec2.FREEDV_MODE.fsk_ldpc_1.value: + elif mode == FREEDV_MODE.fsk_ldpc_1.value: modem.RECEIVE_FSK_LDPC_1 = True self.log.debug("[TNC] Changing listening data mode", mode="fsk_ldpc_1") else: From 62cfdea72b4b55664cf3254c7e42d65dca836bbc Mon Sep 17 00:00:00 2001 From: Paul Kronenwetter Date: Fri, 24 Jun 2022 09:39:56 -0400 Subject: [PATCH 5/5] Add FREEDV_MODE enum usage in test frame. --- tnc/data_handler.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 965d5ccc..b429fff3 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -2557,5 +2557,7 @@ class DATA: time.sleep(2) def send_test_frame(self) -> None: - """Send a test (type 12) frame""" - self.enqueue_frame_for_tx(frame_to_tx=bytearray(126), c2_mode=12) + """Send an empty test frame""" + self.enqueue_frame_for_tx( + frame_to_tx=bytearray(126), c2_mode=FREEDV_MODE.datac3.value + )