Module rpps.mod.modulation

Modulation parent classes

Classes

class APSK
Expand source code
class APSK(Modulation):
    """Amplitude-Phase-shift keying parent"""

Amplitude-Phase-shift keying parent

Ancestors

Inherited members

class ASK
Expand source code
class ASK(Modulation):
    """Amplitude-shift keying parent"""

Amplitude-shift keying parent

Ancestors

Inherited members

class FSK
Expand source code
class FSK(Modulation):
    """Frequency-shift keying parent"""

    def __str__(self):
        return f"{type(self).__name__}:{self.constellation.mapping.str()}"

    def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
        ...

    def demodulate(self, samps):
        # see https://wiki.gnuradio.org/index.php/Quadrature_Demod
        samps = 0.5 * np.angle(samps[0:-1] * np.conj(samps[1:]))
        # return dobject.ModData(samps)
        return samps

    def modulate(self, dobj):
        raise NotImplementedError()

Frequency-shift keying parent

Ancestors

Inherited members

class Modulation
Expand source code
class Modulation(base.rpps.Pipe):
    """Modulation Pipe"""
    __slots__ = ("log", "constellation", "mapping")
    name = "Modulation"
    points = Points([])
    maps = Maps([])

    def __init__(self):  # type: ignore
        self.log = Logger().Child("Modulation").Child(type(self).name)

    def demodulate(self, syms: dobject.IQObject) -> dobject.ModData:
        """Convert IQ samples to bits"""
        raise NotImplementedError()

    def modulate(self, dobj: dobject.BitObject) -> dobject.IQData:
        """Convert bits to IQ samples"""
        raise NotImplementedError()

    def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
        """Draw constellation points on viz"""
        raise NotImplementedError()

    @staticmethod
    def load(name: str, obj: dict):
        """Load modulation from json"""
        raise NotImplementedError()

    def __rmul__(self, other):
        return self.modulate(dobject.ensure_bit(other))

    def __rtruediv__(self, other):
        return self.demodulate(other)

Modulation Pipe

Ancestors

Subclasses

Class variables

var maps
var name
var points

Static methods

def load(name: str, obj: dict)
Expand source code
@staticmethod
def load(name: str, obj: dict):
    """Load modulation from json"""
    raise NotImplementedError()

Load modulation from json

Instance variables

var constellation
Expand source code
class Modulation(base.rpps.Pipe):
    """Modulation Pipe"""
    __slots__ = ("log", "constellation", "mapping")
    name = "Modulation"
    points = Points([])
    maps = Maps([])

    def __init__(self):  # type: ignore
        self.log = Logger().Child("Modulation").Child(type(self).name)

    def demodulate(self, syms: dobject.IQObject) -> dobject.ModData:
        """Convert IQ samples to bits"""
        raise NotImplementedError()

    def modulate(self, dobj: dobject.BitObject) -> dobject.IQData:
        """Convert bits to IQ samples"""
        raise NotImplementedError()

    def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
        """Draw constellation points on viz"""
        raise NotImplementedError()

    @staticmethod
    def load(name: str, obj: dict):
        """Load modulation from json"""
        raise NotImplementedError()

    def __rmul__(self, other):
        return self.modulate(dobject.ensure_bit(other))

    def __rtruediv__(self, other):
        return self.demodulate(other)
var log
Expand source code
class Modulation(base.rpps.Pipe):
    """Modulation Pipe"""
    __slots__ = ("log", "constellation", "mapping")
    name = "Modulation"
    points = Points([])
    maps = Maps([])

    def __init__(self):  # type: ignore
        self.log = Logger().Child("Modulation").Child(type(self).name)

    def demodulate(self, syms: dobject.IQObject) -> dobject.ModData:
        """Convert IQ samples to bits"""
        raise NotImplementedError()

    def modulate(self, dobj: dobject.BitObject) -> dobject.IQData:
        """Convert bits to IQ samples"""
        raise NotImplementedError()

    def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
        """Draw constellation points on viz"""
        raise NotImplementedError()

    @staticmethod
    def load(name: str, obj: dict):
        """Load modulation from json"""
        raise NotImplementedError()

    def __rmul__(self, other):
        return self.modulate(dobject.ensure_bit(other))

    def __rtruediv__(self, other):
        return self.demodulate(other)
var mapping
Expand source code
class Modulation(base.rpps.Pipe):
    """Modulation Pipe"""
    __slots__ = ("log", "constellation", "mapping")
    name = "Modulation"
    points = Points([])
    maps = Maps([])

    def __init__(self):  # type: ignore
        self.log = Logger().Child("Modulation").Child(type(self).name)

    def demodulate(self, syms: dobject.IQObject) -> dobject.ModData:
        """Convert IQ samples to bits"""
        raise NotImplementedError()

    def modulate(self, dobj: dobject.BitObject) -> dobject.IQData:
        """Convert bits to IQ samples"""
        raise NotImplementedError()

    def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
        """Draw constellation points on viz"""
        raise NotImplementedError()

    @staticmethod
    def load(name: str, obj: dict):
        """Load modulation from json"""
        raise NotImplementedError()

    def __rmul__(self, other):
        return self.modulate(dobject.ensure_bit(other))

    def __rtruediv__(self, other):
        return self.demodulate(other)

Methods

def demodulate(self,
syms: IQObject) ‑> ModData
Expand source code
def demodulate(self, syms: dobject.IQObject) -> dobject.ModData:
    """Convert IQ samples to bits"""
    raise NotImplementedError()

Convert IQ samples to bits

def draw_refs(self, points: bool = True, ref: bool = True, ax=None)
Expand source code
def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
    """Draw constellation points on viz"""
    raise NotImplementedError()

Draw constellation points on viz

def modulate(self,
dobj: BitObject) ‑> IQData
Expand source code
def modulate(self, dobj: dobject.BitObject) -> dobject.IQData:
    """Convert bits to IQ samples"""
    raise NotImplementedError()

Convert bits to IQ samples

class PSK (mapping=None)
Expand source code
class PSK(Modulation):
    """Phase-shift keying parent"""

    def __init__(self, mapping = None):
        super().__init__()
        self.constellation = Constellation(type(self).points, log=self.log)

        if mapping is not None:
            self.constellation.mapping =  Mapping(mapping)

    def set_mapping(self, mapping: Mapping):
        """Set modulation mapping"""
        self.constellation.mapping = mapping

    def get_maps(self):
        """Get available maps"""
        return self.maps

    def __str__(self):
        return f"{type(self).__name__}:{self.constellation.mapping.str()}"

    def draw_refs(self, points: bool = True, ref: bool = True, ax=None):
        if ax is None:
            fig = plt.figure()
            ax = fig.add_subplot()
        if points:
            x = self.points.real()
            y = self.points.imag()
            ax.scatter(x=x, y=y, s=200, c="r")
            labels = self.constellation.mapping.arr
            # Add labels using annotate()
            for i, label in enumerate(labels):
                ax.annotate(
                    bin(label)[2:].zfill(self.constellation._bps),
                    (x[i], y[i]),
                    fontsize=20,
                )

        if ref:
            angle = np.linspace(0, 2 * np.pi, 150)
            radius = 1
            x = radius * np.cos(angle)
            y = radius * np.sin(angle)
            ax.plot(x, y, "g")

    def demodulate(self, samps):
        data = self.constellation.demodulate(samps)
        return data

    def modulate(self, dobj):
        syms = self.constellation.modulate(dobj)
        return syms

    @staticmethod
    def load(name, obj):
        def load_complex(comp):
            c = []
            for num in comp:
                c.append(num["real"] + num["imag"] * 1j)
            return c
        def load_magpha(comp):
            c = []
            for num in comp:
                c.append(num["mag"] * np.exp(1j * np.deg2rad(num["pha"])))
            return c

        pnts = load_magpha(obj["Points"])

        maps = [Mapping(m["map"], m["comment"]) for m in obj["Maps"]]

        impl = type(
            name,
            (PSK,),
            dict(name=name, points=Points(pnts), maps=Maps(maps))
        )()
        return impl

Phase-shift keying parent

Ancestors

Methods

def get_maps(self)
Expand source code
def get_maps(self):
    """Get available maps"""
    return self.maps

Get available maps

def set_mapping(self,
mapping: Mapping)
Expand source code
def set_mapping(self, mapping: Mapping):
    """Set modulation mapping"""
    self.constellation.mapping = mapping

Set modulation mapping

Inherited members

class QAM
Expand source code
class QAM(Modulation):
    """Quadrature-Amplitude modulation parent"""

Quadrature-Amplitude modulation parent

Ancestors

Inherited members