Merge branch 'main' into ls-hamlib-test

This commit is contained in:
DJ2LS 2022-01-05 11:54:31 +01:00 committed by GitHub
commit 71be19ecc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 603 additions and 619 deletions

View file

@ -128,6 +128,18 @@ add_test(NAME highsnr_virtual5_P_P_multi_callback_outside
./test_virtual4b.sh")
set_tests_properties(highsnr_virtual5_P_P_multi_callback_outside PROPERTIES PASS_REGULAR_EXPRESSION "DATAC0: 2/4 DATAC1: 2/4 DATAC3: 2/4")
# ARQ test short
add_test(NAME highsnr_ARQ_short
COMMAND sh -c "export LD_LIBRARY_PATH=${CODEC2_BUILD_DIR}/src;
PATH=$PATH:${CODEC2_BUILD_DIR}/src;
cd ${CMAKE_CURRENT_SOURCE_DIR}/test;
python3 test_arq_short.py")
set_tests_properties(highsnr_ARQ_short PROPERTIES PASS_REGULAR_EXPRESSION "ARQ | TX | DATA TRANSMITTED!")
endif()

Binary file not shown.

View file

@ -648,11 +648,11 @@ ipcRenderer.on('action-update-tnc-state', (event, arg) => {
}
// ARQ STATE
if (arg.arq_state == 'DATA') {
if (arg.arq_state == 'True') {
document.getElementById("arq_state").className = "btn btn-warning";
document.getElementById("startTransmission").disabled = true
document.getElementById("stopTransmission").disabled = false
} else if (arg.arq_state == 'IDLE') {
} else if (arg.arq_state == 'False') {
document.getElementById("arq_state").className = "btn btn-secondary";
document.getElementById("startTransmission").disabled = false
document.getElementById("stopTransmission").disabled = true
@ -701,6 +701,15 @@ ipcRenderer.on('action-update-tnc-state', (event, arg) => {
}
document.getElementById("bytes_per_min").innerHTML = arq_bytes_per_minute
// SET BYTES PER MINUTE COMPRESSED
if (typeof(arg.arq_bytes_per_minute) == 'undefined') {
var arq_bytes_per_minute_compressed = 0
} else {
var arq_bytes_per_minute_compressed = Math.round(arg.arq_bytes_per_minute * arg.arq_compression_factor)
}
document.getElementById("bytes_per_min_compressed").innerHTML = arq_bytes_per_minute_compressed
// SET TOTAL BYTES
if (typeof(arg.total_bytes) == 'undefined') {
var total_bytes = 0

View file

@ -152,6 +152,7 @@ client.on('data', function(data) {
arq_rx_n_current_arq_frame: data['ARQ_RX_N_CURRENT_ARQ_FRAME'],
arq_n_arq_frames_per_data_frame: data['ARQ_N_ARQ_FRAMES_PER_DATA_FRAME'],
arq_bytes_per_minute: data['ARQ_BYTES_PER_MINUTE'],
arq_compression_factor: data['ARQ_COMPRESSION_FACTOR'],
total_bytes: data['TOTAL_BYTES'],
arq_transmission_percent: data['ARQ_TRANSMISSION_PERCENT'],
stations: data['STATIONS'],

View file

@ -897,7 +897,8 @@
<div class="input-group input-group-sm"> <span class="input-group-text" id="basic-addon1">Mode</span>
<select class="form-select form-select-sm" aria-label=".form-select-sm" id="datamode">
<!--<option value="14">low SNR (DC0)</option>-->
<option selected value="10">HIGH SNR (DC1)</option>
<option selected value="255">AUTO</option>
<option value="10">HIGH SNR (DC1)</option>
<option value="12">MED SNR (DC3)</option>
</select>
</div>
@ -951,7 +952,7 @@
<!---------------------------------------------------------------------- FOOTER AREA ------------------------------------------------------------>
<nav class="navbar fixed-bottom navbar-light bg-light">
<div class="container-fluid">
<div class="btn-toolbar" style="width:20%" role="toolbar">
<div class="btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm me-2" role="group">
<button class="btn btn-secondary" id="ptt_state" type="button" data-bs-placement="top" data-bs-toggle="tooltip" data-bs-html="true" title="PTT state:<strong class='text-success'>RECEIVING</strong> / <strong class='text-danger'>TRANSMITTING</strong>">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-broadcast-pin" viewBox="0 0 16 16">
@ -975,21 +976,31 @@
</div>
</div>
<div class="container-fluid" style="width:30%">
<div class="container-fluid p-0" style="width:15rem">
<div class="input-group input-group-sm">
<!--<span class="input-group-text" id="basic-addon1"><strong>Freq</strong></span>--> <span class="input-group-text" id="frequency">---</span>
<!--<span class="input-group-text" id="basic-addon1"><strong>Mode</strong></span>--> <span class="input-group-text" id="mode">---</span>
<!--<span class="input-group-text" id="basic-addon1"><strong>BW</strong></span>--> <span class="input-group-text" id="bandwith">---</span>
</div>
</div>
<div class="container-fluid" style="width:30%">
<div class="container-fluid p-0" style="width:12rem">
<div class="input-group input-group-sm"> <span class="input-group-text" id="basic-addon1"><strong>B/min</strong></span>
<span class="input-group-text" id="bytes_per_min">---</span>
<span class="input-group-text" id="basic-addon1"><strong>Total</strong></span>
<span class="input-group-text" id="bytes_per_min" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-html="false" title="raw data rate modem in bytes per minute">---</span>
<span class="input-group-text" id="bytes_per_min_compressed" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-html="false" title="data rate including file compression in bytes per minute">---</span>
</div>
</div>
<div class="container-fluid p-0" style="width:10rem">
<div class="input-group input-group-sm"> <span class="input-group-text" id="basic-addon1"><strong>kBytes</strong></span>
<span class="input-group-text" id="total_bytes">---</span>
</div>
</div>
<div class="container-fluid" style="width:20%">
<div class="container-fluid p-0" style="width:15rem">
<div class="progress" style="height: 30px;">
<div class="progress-bar progress-bar-striped bg-primary" id="transmission_progress" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
<!--<p class="justify-content-center d-flex position-absolute w-100">PROGRESS</p>-->

View file

@ -1,3 +1,34 @@
# Instructions
1. Install:
```
cd FreeDATA
mkdir build
cd build
cmake -DCODEC2_BUILD_DIR=$HOME/codec2/build_linux ..
```
2. List available tests:
```
ctest -N
Test project /home/david/FreeDATA/build
Test #1: 000_audio_tests
Test #2: 001_highsnr_stdio_audio
Total Tests: 2
```
3. Run tests:
```
ctest --output-on-failure
```
4. Run tests verbosely:
```
ctest -V
```
# 001_HIGHSNR_STDIO_AUDIO TEST SUITE
1. Install

28
test/test_arq_short.py Normal file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 23 07:04:24 2020
@author: DJ2LS
"""
import sys
sys.path.insert(0,'..')
sys.path.insert(0,'../tnc')
import data_handler
import argparse
import codec2
parser = argparse.ArgumentParser(description='ARQ TEST')
parser.add_argument('--mode', dest="FREEDV_MODE", type=str, choices=['datac0', 'datac1', 'datac3'])
parser.add_argument('--framesperburst', dest="N_FRAMES_PER_BURST", default=1, type=int)
args = parser.parse_args()
bytes_out = b'{"dt":"f","fn":"zeit.txt","ft":"text\\/plain","d":"data:text\\/plain;base64,MyBtb2Rlcywgb2huZSBjbGFzcwowLjAwMDk2OTQ4MTE4MDk5MTg0MTcKCjIgbW9kZXMsIG9obmUgY2xhc3MKMC4wMDA5NjY1NDUxODkxMjI1Mzk0CgoxIG1vZGUsIG9obmUgY2xhc3MKMC4wMDA5NjY5NzY1NTU4Nzc4MjA5CgMyBtb2Rlcywgb2huZSBjbGFzcwowLjAwMDk2OTQ4MTE4MDk5MTg0MTcKCjIgbW9kZXMsIG9obmUgY2xhc3MKMC4wMDA5NjY1NDUxODkxMjI1Mzk0CgoxIG1vZGUsIG9obmUgY2xhc3MKMC4wMDA5NjY5NzY1NTU4Nzc4MjA5Cg=MyBtb2Rlcywgb2huZSBjbGFzcwowLjAwMDk2OTQ4MTE4MDk5MTg0MTcKCjIgbW9kZXMsIG9obmUgY2xhc3MKMC4wMDA5NjY1NDUxODkxMjI1Mzk0CgoxIG1vZGUsIG9obmUgY2xhc3MKMC4wMDA5NjY5NzY1NTU4Nzc4MjA5CgMyBtb2Rlcywgb2huZSBjbGFzcwowLjAwMDk2OTQ4MTE4MDk5MTg0MTcKCjIgbW9kZXMsIG9obmUgY2xhc3MKMC4wMDA5NjY1NDUxODkxMjI1Mzk0CgoxIG1vZGUsIG9obmUgY2xhc3MKMC4wMDA5NjY5NzY1NTU4Nzc4MjA5CgMyBtb2Rlcywgb2huZSBjbGFzcwowLjAwMDk2OTQ4MTE4MDk5MTg0MTcKCjIgbW9kZXMsIG9obmUgY2xhc3MKMC4wMDA5NjY1NDUxODkxMjI1Mzk0CgoxIG1vZGUsIG9obmUgY2xhc3MKMC4wMDA5NjY5NzY1NTU4Nzc4MjA5Cg=","crc":"123123123"}'
mode = codec2.freedv_get_mode(args.FREEDV_MODE)
n_frames_per_burst = args.N_FRAMES_PER_BURST
data_handler.TESTMODE = True
data_handler.open_dc_and_transmit(bytes_out, mode, n_frames_per_burst)

View file

@ -1,22 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 23 07:04:24 2020
@author: DJ2LS
"""
import sys
sys.path.insert(0,'..')
sys.path.insert(0,'../tnc')
import data_handler
teststring = b'HELLO WORLD'
data_handler.arq_transmit(teststring, 10, 1)

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,7 @@ import numpy as np
import helpers
import static
import data_handler
import re
import queue
import codec2
@ -240,17 +241,17 @@ class RF():
mod_out_postamble = create_string_buffer(n_tx_postamble_modem_samples * 2)
# add empty data to handle ptt toggle time
data_delay_seconds = 250
data_delay = int(self.MODEM_SAMPLE_RATE*(data_delay_seconds/1000))
data_delay_mseconds = 0 #miliseconds
data_delay = int(self.MODEM_SAMPLE_RATE*(data_delay_mseconds/1000))
mod_out_silence = create_string_buffer(data_delay*2)
txbuffer = bytes(mod_out_silence)
for i in range(1,repeats+1):
# write preamble to txbuffer
codec2.api.freedv_rawdatapreambletx(freedv, mod_out_preamble)
time.sleep(0.01)
time.sleep(0.05)
txbuffer += bytes(mod_out_preamble)
# create modulaton for n frames in list
for n in range(0,len(frames)):
@ -267,19 +268,19 @@ class RF():
data = (ctypes.c_ubyte * bytes_per_frame).from_buffer_copy(buffer)
codec2.api.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and save it into mod_out pointer
time.sleep(0.01)
time.sleep(0.05)
txbuffer += bytes(mod_out)
# append postamble to txbuffer
codec2.api.freedv_rawdatapostambletx(freedv, mod_out_postamble)
txbuffer += bytes(mod_out_postamble)
time.sleep(0.01)
time.sleep(0.05)
# add delay to end of frames
samples_delay = int(self.MODEM_SAMPLE_RATE*(repeat_delay/1000))
mod_out_silence = create_string_buffer(samples_delay*2)
txbuffer += bytes(mod_out_silence)
time.sleep(0.01)
#time.sleep(0.05)
# resample up to 48k (resampler works on np.int16)
x = np.frombuffer(txbuffer, dtype=np.int16)
@ -294,7 +295,9 @@ class RF():
# if data is shorter than the expcected audio frames per buffer we need to append 0
# to prevent the callback from stucking/crashing
if len(c) < self.AUDIO_FRAMES_PER_BUFFER_RX*2:
c += bytes(self.AUDIO_FRAMES_PER_BUFFER_RX*2 - len(c))
delta = bytes(self.AUDIO_FRAMES_PER_BUFFER_RX*2 - len(c))
c += delta
structlog.get_logger("structlog").debug("[TNC] mod out shorter than audio buffer", delta=len(delta))
self.modoutqueue.put(c)
# maybe we need to toggle PTT before craeting modulation because of queue processing
@ -302,21 +305,21 @@ class RF():
while not self.modoutqueue.empty():
pass
static.PTT_STATE = self.hamlib.set_ptt(False)
self.c_lib.freedv_close(freedv)
return True
def audio(self):
try:
print(f"starting pyaudio callback", file=sys.stderr)
structlog.get_logger("structlog").debug("[TNC] starting pyaudio callback")
self.audio_stream.start_stream()
except Exception as e:
print(f"pyAudio error: {e}", file=sys.stderr)
structlog.get_logger("structlog").error("[TNC] starting pyaudio callback failed", e=e)
while self.audio_stream.is_active():
while self.datac0_buffer.nbuffer >= self.datac0_nin:
# demodulate audio
nbytes = codec2.api.freedv_rawdatarx(self.datac0_freedv, self.datac0_bytes_out, self.datac0_buffer.buffer.ctypes)
self.datac0_buffer.pop(self.datac0_nin)
@ -327,6 +330,7 @@ class RF():
self.calculate_snr(self.datac0_freedv)
while self.datac1_buffer.nbuffer >= self.datac1_nin:
# demodulate audio
nbytes = codec2.api.freedv_rawdatarx(self.datac1_freedv, self.datac1_bytes_out, self.datac1_buffer.buffer.ctypes)
self.datac1_buffer.pop(self.datac1_nin)
@ -337,6 +341,7 @@ class RF():
self.calculate_snr(self.datac1_freedv)
while self.datac3_buffer.nbuffer >= self.datac3_nin:
# demodulate audio
nbytes = codec2.api.freedv_rawdatarx(self.datac3_freedv, self.datac3_bytes_out, self.datac3_buffer.buffer.ctypes)
self.datac3_buffer.pop(self.datac3_nin)
@ -344,8 +349,9 @@ class RF():
if nbytes == self.datac3_bytes_per_frame:
self.dataqueue.put([self.datac3_bytes_out, self.datac3_freedv ,self.datac3_bytes_per_frame])
self.get_scatter(self.datac3_freedv)
self.calculate_snr(self.datac3_freedv)
self.calculate_snr(self.datac3_freedv)
@ -353,8 +359,11 @@ class RF():
# worker for FIFO queue for processing received frames
def worker(self):
while True:
time.sleep(0.1)
time.sleep(0.01)
data = self.dataqueue.get()
# data[0] = bytes_out
# data[1] = freedv session
# data[2] = bytes_per_frame
self.process_data(data[0], data[1], data[2])
self.dataqueue.task_done()
@ -366,7 +375,7 @@ class RF():
# we could also create an own function, which returns True.
def process_data(self, bytes_out, freedv, bytes_per_frame):
if bytes(bytes_out[1:2]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[6:7]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[1:2]) == b'\x01':
if bytes(bytes_out[1:2]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[3:4]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[1:2]) == b'\x01':
# CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------
frametype = int.from_bytes(bytes(bytes_out[:1]), "big")
@ -378,39 +387,47 @@ class RF():
#print("Freq-Offset: " + str(frequency_offset))
if 50 >= frametype >= 10:
# get snr of received data
snr = self.calculate_snr(freedv)
structlog.get_logger("structlog").debug("[TNC] RX SNR", snr=snr)
# send payload data to arq checker without CRC16
data_handler.arq_data_received(bytes(bytes_out[:-2]), bytes_per_frame)
data_handler.arq_data_received(bytes(bytes_out[:-2]), bytes_per_frame, snr, freedv)
#print("static.ARQ_RX_BURST_BUFFER.count(None) " + str(static.ARQ_RX_BURST_BUFFER.count(None)))
if static.RX_BURST_BUFFER.count(None) <= 1:
logging.debug("FULL BURST BUFFER ---> UNSYNC")
# if we received the last frame of a burst or the last remaining rpt frame, do a modem unsync
if static.RX_BURST_BUFFER.count(None) <= 1 or (frame+1) == n_frames_per_burst:
structlog.get_logger("structlog").debug(f"LAST FRAME OF BURST --> UNSYNC {frame+1}/{n_frames_per_burst}")
self.c_lib.freedv_set_sync(freedv, 0)
# BURST ACK
elif frametype == 60:
logging.debug("ACK RECEIVED....")
data_handler.burst_ack_received()
structlog.get_logger("structlog").debug("ACK RECEIVED....")
data_handler.burst_ack_received(bytes_out[:-2])
# FRAME ACK
elif frametype == 61:
logging.debug("FRAME ACK RECEIVED....")
structlog.get_logger("structlog").debug("FRAME ACK RECEIVED....")
data_handler.frame_ack_received()
# FRAME RPT
elif frametype == 62:
logging.debug("REPEAT REQUEST RECEIVED....")
structlog.get_logger("structlog").debug("REPEAT REQUEST RECEIVED....")
data_handler.burst_rpt_received(bytes_out[:-2])
# FRAME NACK
elif frametype == 63:
structlog.get_logger("structlog").debug("FRAME NOT ACK RECEIVED....")
data_handler.frame_nack_received(bytes_out[:-2])
# CQ FRAME
elif frametype == 200:
logging.debug("CQ RECEIVED....")
structlog.get_logger("structlog").debug("CQ RECEIVED....")
data_handler.received_cq(bytes_out[:-2])
# PING FRAME
elif frametype == 210:
logging.debug("PING RECEIVED....")
structlog.get_logger("structlog").debug("PING RECEIVED....")
frequency_offset = self.get_frequency_offset(freedv)
#print("Freq-Offset: " + str(frequency_offset))
data_handler.received_ping(bytes_out[:-2], frequency_offset)
@ -418,7 +435,7 @@ class RF():
# PING ACK
elif frametype == 211:
logging.debug("PING ACK RECEIVED....")
structlog.get_logger("structlog").debug("PING ACK RECEIVED....")
# early detection of frequency offset
#frequency_offset = int.from_bytes(bytes(bytes_out[9:11]), "big", signed=True)
#print("Freq-Offset: " + str(frequency_offset))
@ -433,19 +450,21 @@ class RF():
# ARQ FILE TRANSFER RECEIVED!
elif frametype == 225:
logging.debug("ARQ arq_received_data_channel_opener")
structlog.get_logger("structlog").debug("ARQ arq_received_data_channel_opener")
data_handler.arq_received_data_channel_opener(bytes_out[:-2])
# ARQ CHANNEL IS OPENED
elif frametype == 226:
logging.debug("ARQ arq_received_channel_is_open")
structlog.get_logger("structlog").debug("ARQ arq_received_channel_is_open")
data_handler.arq_received_channel_is_open(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE
# this is outdated and we may remove it
elif frametype == 230:
logging.debug("BEACON RECEIVED")
structlog.get_logger("structlog").debug("BEACON RECEIVED")
data_handler.received_beacon(bytes_out[:-2])
# TESTFRAMES
elif frametype == 255:
structlog.get_logger("structlog").debug("TESTFRAME RECEIVED", frame=bytes_out[:])
@ -455,6 +474,7 @@ class RF():
# DO UNSYNC AFTER LAST BURST by checking the frame nums against the total frames per burst
# this should be changed to a timeout based unsync
if frame == n_frames_per_burst:
logging.info("LAST FRAME ---> UNSYNC")
self.c_lib.freedv_set_sync(freedv, 0) # FORCE UNSYNC
@ -508,11 +528,13 @@ class RF():
self.c_lib.freedv_get_modem_stats(freedv, byref(
modem_stats_sync), byref(modem_stats_snr))
modem_stats_snr = modem_stats_snr.value
try:
static.SNR = round(modem_stats_snr, 1)
return static.SNR
except:
static.SNR = 0
return static.SNR
def update_rig_data(self):
while True:
@ -553,3 +575,13 @@ class RF():
static.FFT = [0] * 320
else:
pass
def get_bytes_per_frame(self, mode):
freedv = cast(codec2.api.freedv_open(mode), c_void_p)
# get number of bytes per frame for mode
return int(codec2.api.freedv_get_bits_per_modem_frame(freedv)/8)
def set_frames_per_burst(self, n_frames_per_burst):
codec2.api.freedv_set_frames_per_burst(self.datac1_freedv,n_frames_per_burst)
codec2.api.freedv_set_frames_per_burst(self.datac3_freedv,n_frames_per_burst)

View file

@ -31,6 +31,7 @@ import time
import static
import data_handler
import helpers
import sys
@ -121,7 +122,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
PING_THREAD = threading.Thread(target=data_handler.transmit_ping, args=[dxcallsign], name="PING")
PING_THREAD.start()
# and static.ARQ_READY_FOR_DATA == True: # and static.ARQ_STATE == 'CONNECTED' :
if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile":
static.TNC_STATE = 'BUSY'
@ -191,7 +192,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
print(" >>> STOPPING TRANSMISSION <<<")
structlog.get_logger("structlog").warning("[TNC] Stopping transmission!")
static.TNC_STATE = 'IDLE'
static.ARQ_STATE = 'IDLE'
static.ARQ_STATE = False
# SETTINGS AND STATUS ---------------------------------------------
@ -248,6 +249,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
"RX_MSG_BUFFER_LENGTH": str(len(static.RX_MSG_BUFFER)),
"ARQ_BYTES_PER_MINUTE": str(static.ARQ_BYTES_PER_MINUTE),
"ARQ_BYTES_PER_MINUTE_BURST": str(static.ARQ_BYTES_PER_MINUTE_BURST),
"ARQ_COMPRESSION_FACTOR": str(static.ARQ_COMPRESSION_FACTOR),
"ARQ_TRANSMISSION_PERCENT": str(static.ARQ_TRANSMISSION_PERCENT),
"TOTAL_BYTES": str(static.TOTAL_BYTES),
"INFO" : static.INFO,
@ -322,8 +324,7 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
print(exc_type, fname, exc_tb.tb_lineno)
print("############ END OF ERROR #######################")
print("reset of connection...")
structlog.get_logger("structlog").warning("[TNC] Stopping transmission!")
structlog.get_logger("structlog").warning("[TNC] reset of tcp/ip connection...")
#socketTimeout = 0
structlog.get_logger("structlog").error("[TNC] Network error", e = sys.exc_info()[0])

View file

@ -72,12 +72,14 @@ ARQ_BYTES_PER_MINUTE_BURST = 0
ARQ_BYTES_PER_MINUTE = 0
ARQ_BITS_PER_SECOND_BURST = 0
ARQ_BITS_PER_SECOND = 0
ARQ_COMPRESSION_FACTOR = 0
ARQ_TRANSMISSION_PERCENT = 0
TOTAL_BYTES = 0
#CHANNEL_STATE = 'RECEIVING_SIGNALLING'
TNC_STATE = 'IDLE'
ARQ_STATE = 'IDLE'
ARQ_STATE = False
# BEACON STATE
BEACON_STATE = False
@ -86,7 +88,7 @@ BEACON_STATE = False
RX_BUFFER = []
RX_MSG_BUFFER = []
RX_BURST_BUFFER = []
RX_FRAME_BUFFER = []
RX_FRAME_BUFFER = b''
#RX_BUFFER_SIZE = 0
# ------- HEARD STATIOS BUFFER