Add files via upload

This commit is contained in:
DJ2LS 2020-12-12 19:59:37 +01:00 committed by GitHub
parent 156770a39c
commit ae7213b1e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 409 additions and 0 deletions

92
__main__.py Normal file
View file

@ -0,0 +1,92 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 11 16:54:35 2020
@author: DJ2LS
"""
import sys
import logging
import argparse
import socketserver
import freedv
import sound
import tnc
import commands
def main():
parser = argparse.ArgumentParser(description='Simons TEST TNC')
parser.add_argument('--rx-sound-device', dest="audio_input_device", default=False, help="The sound card used to rx.", type=int)
parser.add_argument('--tx-sound-device', dest="audio_output_device", default=False, help="The sound card used to tx.", type=int)
parser.add_argument('--list-sound-device', dest="list_sound_devices", action='store_true', help="List audio devices")
parser.add_argument('--port', dest="socket_port", default=9000, help="Set the port, the socket is listening on.", type=int)
args = parser.parse_args()
if args.list_sound_devices:
for line in commands.Helpers.getAudioDevices():
print(line)
sys.exit(0)
logger = logging.getLogger()
logger.setLevel("INFO") #DEBUG>INFO>WARNING>ERROR>CRITICAL
logger.info("SIMONS ERSTES TNC PROGRAMM....DURCHHALTEN!")
#LADE FreeDV Klasse sonst Fehler
try:
modem = freedv.FreeDV()
except OSError:
logger.error("FREEDV NICHT GEFUNDEN")
sys.exit(0)
#LADE Audio Klasse sonst Fehler
try:
audio = sound.Audio(
defaultFrames = 1024 * 8,
audio_input_device=args.audio_input_device,
audio_output_device=args.audio_output_device,
tx_sample_state = None,
audio_sample_rate=48000,
modem_sample_rate=8000,
frames_per_buffer=1024,
audio_channels=1,
)
audio.Record()
except OSError:
logger.error("AUDIO NICHT GEFUNDEN")
sys.exit(0)
#LADE TNC Klasse sonst Fehler
try:
HOST, PORT = "localhost", args.socket_port
try:
logger.info("Starting SOCKET SERVER")
server = socketserver.TCPServer((HOST, PORT), tnc.MyTCPHandler)
server.serve_forever()
finally:
server.server_close()
except OSError:
logger.error("TNC NICHT GEFUNDEN")
sys.exit(0)
####################### TEST BEREICH ############################
#################################################################
if __name__ == "__main__":
main()

133
commands.py Normal file
View file

@ -0,0 +1,133 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 11 23:10:21 2020
@author: DJ2LS
"""
import freedv
import logging
import sound
import pyaudio
class Helpers():
def crc16(data: bytes):
#https://stackoverflow.com/a/60604183
xor_in = 0x0000 # initial value
xor_out = 0x0000 # final XOR value
poly = 0x8005 # generator polinom (normal form)
reg = xor_in
for octet in data:
# reflect in
for i in range(8):
topbit = reg & 0x8000
if octet & (0x80 >> i):
topbit ^= 0x8000
reg <<= 1
if topbit:
reg ^= poly
reg &= 0xFFFF
# reflect out
return reg ^ xor_out
def getAudioDevices():
p = pyaudio.PyAudio()
info = p.get_host_api_info_by_index(0)
numdevices = info.get('deviceCount')
for i in range(0, numdevices):
if (p.get_device_info_by_host_api_device_index(0,i).get('maxInputChannels')) > 0:
print("Input Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0, i).get('name'))
if (p.get_device_info_by_host_api_device_index(0,i).get('maxOutputChannels')) > 0:
print("Output Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0, i).get('name'))
class TX():
def Broadcast(self, bcdata):
modem = freedv.FreeDV()
audio = sound.Audio()
#preamble = b'\x00' * modem.bytes_per_frame * 2 #SET PREAMPLE
preamble = b'\x00\x00\x00'
header = b'' # SET HEADER
#postamble = b'\xFF' * modem.bytes_per_frame# * 2 # SET POSTAMPLE
frame = preamble + header + bcdata# + postamble # COMBINE PREAMPLE, HEADER, DATA AND POSTAMPLE
logging.info(hex(Helpers.crc16(bcdata)))
logging.info(len(hex(Helpers.crc16(bcdata))))
#testcrc = modem.c_lib.freedv_gen_crc16(frame,modem.payload_per_frame)
logging.info("BYTES PER FRAME: " + str(modem.bytes_per_frame))
logging.info("PAYLOAD PER FRAME: " + str(modem.payload_per_frame))
logging.info("FRAME LENGTH: " + str(len(frame)))
#logging.info(str(len(frame)/modem.bytes_per_frame))
#logging.info(str(len(frame) % modem.bytes_per_frame))
# Check if data is divisable by bytes per frame. If yes (0) skip, If no (>0) fill up with frames
checkframe = len(frame) % modem.bytes_per_frame
# filecrc = binascii.crc16(frame).to_bytes(2, byteorder='big', signed=False)
#if checkframe != 0:
# filler = bytes(modem.bytes_per_frame - (len(frame) % modem.bytes_per_frame))
# logging.info("FILLER: " + str(len(filler)))
#
# frame = frame + filler
# if len(filler) == 6:
# filler * 2
#frame = frame + filler
#checkframe = len(frame) % modem.bytes_per_frame * 2
#logging.info("CHECKFRAME: " + str(checkframe))
#logging.info("FRAME LENGTH: " + str(len(frame)))
# Pull frame into a datalist to work as a simple buffer
data_list = [frame[i:i+modem.bytes_per_frame*2] for i in range(0, len(frame), modem.bytes_per_frame*2)] # PACK DATAFRAME TO A LIST WHICH IS AS BIG AS THE FRAME SIZE OF FREEDV MODE
#data_list.append(b'0x00')
length = len(data_list) # GET LENGTH OF DATA LIST
# Loop through data list for every item and modulate it
for i in range(length): # LOOP THROUGH DATA LIST
#crc = Helpers.crc16(data_list[i])
#logging.info(hex(crc))
logging.info(data_list[i])
modulated_data = modem.Modulate(data_list[i])
#logging.info(bytes(modulated_data))
audio.Play(modulated_data)
class RX():
def ReceiveAudio():
audio = sound.Audio.Record()
frame = freedv.FreeDV.Demodulate(audio)
logging.info(frame)

69
freedv.py Normal file
View file

@ -0,0 +1,69 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 11 16:58:35 2020
@author: DJ2LS
"""
import ctypes
from ctypes import *
import pathlib
import logging
import sound
class FreeDV():
def __init__(self):
libname = pathlib.Path().absolute() / "libcodec2.so"
self.c_lib = ctypes.CDLL(libname)
self.audio = sound.Audio()
self.freedv = self.c_lib.freedv_open(3)
self.bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(self.freedv)/8)
self.payload_per_frame = self.bytes_per_frame -2
logging.info("FreeDV Initialized")
# MODULATION-OUT OBJECT
def ModulationOut(self):
return (c_short * self.c_lib.freedv_get_n_nom_modem_samples(self.freedv))
# MODULATION-IN OBJECT
def ModulationIn(self):
return (c_short * self.c_lib.freedv_get_n_nom_modem_samples(self.freedv))
# DataFrame
def DataFrame(self):
return (ctypes.c_short * self.bytes_per_frame)
# GET DATA AND MODULATE IT
def Modulate(self,data_out):
mod_out = self.ModulationOut()() # new modulation object and get pointer to it
data = (ctypes.c_short * self.bytes_per_frame).from_buffer_copy(data_out)
#self.freedv_rawdatapreambletx(self.freedv, mod_out) # SEND PREAMBLE
self.c_lib.freedv_rawdatatx(self.freedv,mod_out,data) # SEND DATA
#logging.info(bytes(mod_out))
return mod_out
# DEMODULATE DATA AND RETURN IT
def Demodulate(self,modulation_in):
mod_in = self.ModulationIn()() # new modulation object and get pointer to it
data_in = self.DataFrame()()
self.c_lib.freedv_rawdatarx(self.freedv, data_in, mod_in)
return data_in

81
sound.py Normal file
View file

@ -0,0 +1,81 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 11 17:47:32 2020
@author: DJ2LS
"""
import pyaudio
import audioop
import logging
class Audio():
def __init__(self,
defaultFrames = 1024 * 8,
audio_input_device=2,
audio_output_device=0,
tx_sample_state = None,
rx_sample_state = None,
audio_sample_rate=48000,
modem_sample_rate=8000,
frames_per_buffer=1024,
audio_channels=1,
#format = pyaudio.paInt16,
stream = None,
):
self.p = pyaudio.PyAudio()
self.defaultFrames = defaultFrames
self.audio_input_device = audio_input_device
self.audio_output_device = audio_output_device
self.tx_sample_state = tx_sample_state
self.rx_sample_state = rx_sample_state
self.audio_sample_rate = audio_sample_rate
self.modem_sample_rate = modem_sample_rate
self.frames_per_buffer = frames_per_buffer
self.audio_channels = audio_channels
self.format = pyaudio.paInt16
self.stream = None
logging.info("AUDIO Initialized")
# PLAY MODULATED AUDIO
def Play(self, modulation):
stream_tx = self.p.open(format=self.format,
channels=self.audio_channels,
rate=self.audio_sample_rate,
frames_per_buffer=self.frames_per_buffer,
output=True,
output_device_index=self.audio_output_device,
)
audio = audioop.ratecv(modulation,2,1,self.modem_sample_rate, self.audio_sample_rate, self.tx_sample_state)
stream_tx.write(audio[0])
stream_tx.close()
#self.p.terminate()
# RECORD AUDIO
def Record(self):
stream_rx = self.p.open(format=self.format,
channels=self.audio_channels,
rate=self.audio_sample_rate,
frames_per_buffer=self.frames_per_buffer, #modem.get_n_max_modem_samples()
input=True,
input_device_index=self.audio_input_device,
)
#audio = audioop.ratecv(modulation,2,1,modem_sample_rate, audio_sample_rate, tx_sample_state)
#stream.read(audio[0])
data = stream_rx.read(self.defaultFrames)
data = audioop.ratecv(data,2,1,self.audio_sample_rate, self.modem_sample_rate, self.rx_sample_state)
#stream_rx.close()
#self.p.terminate()
return data

34
tnc.py Normal file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 11 20:06:55 2020
@author: DJ2LS
"""
import logging
import socketserver
import freedv
import commands
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
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!")
# BROADCAST PARSER ###########################################################
#if self.data == b'BC':
if self.data.startswith(b'BC:'):
data = self.data.split(b'BC:')
commands.TX.Broadcast(bytes(data[1]),bytes(data[1]))
#commands.TX.Broadcast(data,data)