From faa144c050972d518b8e953b4396e6b566cd2b03 Mon Sep 17 00:00:00 2001 From: andreas128 Date: Sat, 5 Aug 2017 22:29:04 +0100 Subject: Add Adapt and Model, Update for minimum working pipeline --- dpd/main.py | 20 +++++-- dpd/src/Adapt.py | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ dpd/src/Dab_Util.py | 24 +++++++++ dpd/src/Measure.py | 48 +++++++++-------- dpd/src/Model.py | 33 ++++++++++++ 5 files changed, 250 insertions(+), 28 deletions(-) create mode 100644 dpd/src/Adapt.py create mode 100644 dpd/src/Model.py (limited to 'dpd') diff --git a/dpd/main.py b/dpd/main.py index 427bc28..1cb6021 100644 --- a/dpd/main.py +++ b/dpd/main.py @@ -1,5 +1,7 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +"""This Python script calculates and updates the parameter of the digital +predistortion module of the ODR-DabMod. More precisely the complex +coefficients of the polynom which is used for predistortion.""" import logging logging.basicConfig(format='%(asctime)s - %(module)s - %(levelname)s - %(message)s', @@ -7,16 +9,24 @@ logging.basicConfig(format='%(asctime)s - %(module)s - %(levelname)s - %(message filename='/tmp/dpd.log', filemode='w', level=logging.DEBUG) + import src.Measure as Measure +import src.Model as Model +import src.Adapt as Adapt port = 50055 +port_rc = 9400 +coef_path = "/home/andreas/dab/ODR-DabMod/polyCoefsCustom" num_req = 10240 -m = Measure.Measure(port, num_req) +meas = Measure.Measure(port, num_req) +adapt = Adapt.Adapt(port_rc, coef_path) +coefs = adapt.get_coefs() +model = Model.Model(coefs) -logging.info("Do measurement") -m.get_samples() -logging.info("Done") +txframe_aligned, rxframe_aligned = meas.get_samples() +coefs = model.get_next_coefs(txframe_aligned, rxframe_aligned) +adapt.set_coefs(coefs) # The MIT License (MIT) # diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py new file mode 100644 index 0000000..b86f604 --- /dev/null +++ b/dpd/src/Adapt.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +""" +This module is used to change settings of ODR-DabMod using +the ZMQ remote control socket. +""" + +import zmq +import exceptions +import logging +import numpy as np + +port = 9400 + +class Adapt: + """Uses the ZMQ remote control to change parameters + of the DabMod + + Parameters + ---------- + port : int + Port at which the ODR-DabMod is listening to connect the + ZMQ remote control. + """ + + def __init__(self, port, coef_path): + logging.info("Instantiate Adapt object") + self.port = port + self.coef_path = coef_path + self.host = "localhost" + self._connect() + + def _connect(self): + """Establish the connection to ODR-DabMod using + a ZMQ socket that is in request mode (Client)""" + context = zmq.Context() + sock = context.socket(zmq.REQ) + sock.connect("tcp://%s:%d" % (self.host, self.port)) + + sock.send(b"ping") + data = sock.recv_multipart() + + if data != ['ok']: + raise exceptions.RuntimeError( + "Could not connect to server %s %d." % + (self.host, self.port)) + + self.sock = sock + + def send_receive(self, message): + """Used to send a message to the ODR-DabMod. It always + returns a answer it also receives the next message + from ODR-DabMod over the ZMQ remote control socket. + + Parameter + --------- + message : str + The message string that will be sent to + the receiver. + """ + logging.info("Send message: %s" % message) + msg_parts = message.split(" ") + for i, part in enumerate(msg_parts): + if i == len(msg_parts) - 1: + f = 0 + else: + f = zmq.SNDMORE + + self.sock.send(part.encode(), flags=f) + + data = self.sock.recv_multipart() + logging.info("Received message: %s" % message) + return data + + def set_txgain(self, gain): + """Set a new txgain for the ORD-DabMod. + + Parameters + ---------- + gain : int + Value that will be set to be txgain + """ + if gain < 0 or gain > 89: + raise exceptions.ValueError("Gain has to be in [0,89]") + return self.send_receive("set uhd txgain %d" % gain) + + def get_txgain(self): + """Get the txgain value in dB for the ORD-DabMod.""" + return self.send_receive("get uhd txgain") + + def set_rxgain(self, gain): + """Set a new rxgain for the ORD-DabMod. + + Parameters + ---------- + gain : int + Value that will be set to be rxgain + """ + if gain < 0 or gain > 89: + raise exceptions.ValueError("Gain has to be in [0,89]") + return self.send_receive("set uhd rxgain %d" % gain) + + def get_rxgain(self): + """Get the rxgain value in dB for the ORD-DabMod.""" + return self.send_receive("get uhd rxgain") + + def _read_coef_file(self): + coefs_complex = [] + f = open(self.coef_path, 'r') + lines = f.readlines() + n_coefs = lines[0] + coefs = [float(l) for l in lines[1:]] + for r, c in zip(coefs[0::2], coefs[1::2]): + coefs_complex.append(np.complex64(r + 1j * c)) + f.close() + return coefs_complex + + def get_coefs(self): + return self._read_coef_file() + + def _write_coef_file(self, coefs_complex): + coef_path = "/home/andreas/dab/ODR-DabMod/polyCoefsCustom" + f = open(coef_path, 'w') + f.write(str(len(coefs_complex)) + "\n") + for coef in coefs_complex: + f.write(str(coef.real) + "\n") + f.write(str(coef.imag) + "\n") + f.close() + + def set_coefs(self, coefs_complex): + self._write_coef_file(coefs_complex) + self.send_receive("set memlesspoly coeffile polyCoefsCustom") + + # The MIT License (MIT) + # + # Copyright (c) 2017 Andreas Steger + # + # Permission is hereby granted, free of charge, to any person obtaining a copy + # of this software and associated documentation files (the "Software"), to deal + # in the Software without restriction, including without limitation the rights + # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + # copies of the Software, and to permit persons to whom the Software is + # furnished to do so, subject to the following conditions: + # + # The above copyright notice and this permission notice shall be included in all + # copies or substantial portions of the Software. + # + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + # SOFTWARE. diff --git a/dpd/src/Dab_Util.py b/dpd/src/Dab_Util.py index 73ae852..ba008b6 100644 --- a/dpd/src/Dab_Util.py +++ b/dpd/src/Dab_Util.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import numpy as np import scipy import matplotlib.pyplot as plt @@ -91,3 +93,25 @@ class Dab_Util: return np.memmap(filename, dtype=np.complex64, mode='r', offset=64/8*offset) else: return np.memmap(filename, dtype=np.complex64, mode='r', offset=64/8*offset, shape=length) + +# The MIT License (MIT) +# +# Copyright (c) 2017 Andreas Steger +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. diff --git a/dpd/src/Measure.py b/dpd/src/Measure.py index a8da137..d3d9320 100644 --- a/dpd/src/Measure.py +++ b/dpd/src/Measure.py @@ -1,24 +1,4 @@ -# The MIT License (MIT) -# -# Copyright (c) 2017 Andreas Steger -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. +# -*- coding: utf-8 -*- import sys import socket @@ -36,7 +16,7 @@ class Measure: """Collect Measurement from DabMod""" def __init__(self, port, num_samples_to_request): """""" - logging.info("Initalized Measure class") + logging.info("Instantiate Measure object") self.sizeof_sample = 8 # complex floats self.port = port self.num_samples_to_request = num_samples_to_request @@ -67,7 +47,7 @@ class Measure: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('localhost', self.port)) - logging.debug("Send version"); + logging.debug("Send version") s.sendall(b"\x01") logging.debug("Send request for {} samples".format(self.num_samples_to_request)) @@ -102,3 +82,25 @@ class Measure: du = DU.Dab_Util(8192000) txframe_aligned, rxframe_aligned = du.subsample_align(txframe, rxframe) return txframe_aligned, rxframe_aligned + +# The MIT License (MIT) +# +# Copyright (c) 2017 Andreas Steger +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. diff --git a/dpd/src/Model.py b/dpd/src/Model.py new file mode 100644 index 0000000..a7bc63b --- /dev/null +++ b/dpd/src/Model.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +class Model: + """Calculates new coefficients using the measurement and the old + coefficients""" + + def __init__(self, coefs): + self.coefs = coefs + + def get_next_coefs(self, txframe_aligned, rxframe_aligned): + return self.coefs + +# The MIT License (MIT) +# +# Copyright (c) 2017 Andreas Steger +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. -- cgit v1.2.3