diff --git a/show.py b/show.py index 53e7a0a..21b848d 100644 --- a/show.py +++ b/show.py @@ -7,7 +7,7 @@ def constellation(y, title): theta = np.linspace(0, 2*np.pi, 1000) pylab.plot(y.real, y.imag, '.') pylab.plot(np.cos(theta), np.sin(theta), ':') - points = np.array(sigproc.modulator.points) + points = np.array(sigproc.modulator.symbols) pylab.plot(points.real, points.imag, 'o') pylab.grid('on') pylab.axis('equal') diff --git a/sigproc.py b/sigproc.py index b514024..0932323 100644 --- a/sigproc.py +++ b/sigproc.py @@ -24,18 +24,21 @@ def train(S, training): return lambda x: lfilter(b=[b0, b1], a=[1, -a1], x=x) class QAM(object): - def __init__(self, bits_per_symbol, radii): + def __init__(self, symbols): self._enc = {} - index = 0 - N = (2 ** bits_per_symbol) / len(radii) - for a in radii: - for i in range(N): - k = tuple(int(index & (1 << j) != 0) for j in range(bits_per_symbol)) - v = np.exp(2j * i * np.pi / N) - self._enc[k] = v * a - index += 1 + symbols = np.array(list(symbols)) + bits_per_symbol = np.log2(len(symbols)) + bits_per_symbol = np.round(bits_per_symbol) + N = (2 ** bits_per_symbol) + assert N == len(symbols) + bits_per_symbol = int(bits_per_symbol) + + for i, v in enumerate(symbols): + bits = tuple(int(i & (1 << j) != 0) for j in range(bits_per_symbol)) + self._enc[bits] = v + self._dec = {v: k for k, v in self._enc.items()} - self.points = self._enc.values() + self.symbols = symbols self.bits_per_symbol = bits_per_symbol def encode(self, bits): @@ -48,10 +51,12 @@ class QAM(object): def decode(self, symbols): for s in symbols: - index = np.argmin(np.abs(s - self.points)) - yield self._dec[ self.points[index] ] + index = np.argmin(np.abs(s - self.symbols)) + yield self._dec[ self.symbols[index] ] -modulator = QAM(bits_per_symbol=4, radii=[1.0, 0.6]) +_xs, _ys = np.linspace(-1, 1, 4), np.linspace(-1, 1, 4) # QAM-16 +_symbols = np.array([complex(x, y) for x in _xs for y in _ys]) * np.sqrt(0.5) +modulator = QAM(_symbols) def clip(x, lims): return min(max(x, lims[0]), lims[1]) diff --git a/test_sigproc.py b/test_sigproc.py index 5da0d5a..a961c2e 100644 --- a/test_sigproc.py +++ b/test_sigproc.py @@ -2,10 +2,12 @@ import sigproc import itertools import common import numpy as np +import random def test_qam(): - q = sigproc.QAM(bits_per_symbol=8, radii=[0.25, 0.5, 0.75, 1.0]) - bits = [(1,1,0,1,0,0,1,0), (0,1,0,0,0,1,1,1)] + q = sigproc.QAM(sigproc._symbols) + r = random.Random(0) + bits = [tuple(r.randint(0, 1) for j in range(4)) for i in range(1024)] stream = itertools.chain(*bits) S = q.encode(list(stream)) decoded = list(q.decode(list(S)))