diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b42097e865c14e2dde215fccdd2e303d6c103b36
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+**/__pycache__/
\ No newline at end of file
diff --git a/controlPlatform/__init__.py b/controlPlatform/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..197f7ec6e22a0392ef81d12dc326863c44ba24cf
--- /dev/null
+++ b/controlPlatform/__init__.py
@@ -0,0 +1,14 @@
+from .extensions.baseband import Baseband
+from .extensions.basic import Basic
+from .extensions.boot import Boot
+from .extensions.calibrator import Calibrator
+from .extensions.central import Central
+from .extensions.dds import Dds
+from .extensions.fmcw import Fmcw
+from .extensions.pll import Pll
+from .extensions.radar import Radar
+from .extensions.receiver import Receiver
+from .extensions.transmitter import Transmitter
+from .extensions.trigger import Trigger
+from .extensions.sampler import Sampler
+from .extension import Interface, Packager
\ No newline at end of file
diff --git a/controlPlatform/extension.py b/controlPlatform/extension.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c2c8108659b6cdfa81a8b66e4c384dedf982372
--- /dev/null
+++ b/controlPlatform/extension.py
@@ -0,0 +1,111 @@
+import struct
+import logging
+
+class Packager():
+	"""
+	Generates a bytestream for transmission of data. It gets the configuration bytes and the raw data to send.
+
+	The raw data can be:
+		single values of int or float
+		lists of int or float (or both)
+	"""
+
+	def __init__(self):
+		super().__init__()
+
+	def __singleToByteArray(self, x, length):
+		"""
+		Converts a single value of float or int to its representation in bytes.
+		"""
+		if isinstance(x, float):
+			return bytearray(struct.pack('<d', x))
+		elif isinstance(x, int):
+			return bytearray(x.to_bytes(length, 'little'))
+
+	def __toByteArray(self, x, length):
+		"""
+		Converts a value or list to a bytestream.
+		"""
+		if isinstance(x, list):
+			listByteArray = bytearray()
+			for element in x:
+				listByteArray += self.__singleToByteArray(element, length)
+			return listByteArray
+		else:
+			return self.__singleToByteArray(x, length)
+
+	def serializeConfig(self, conf, inputs = None, length = None):
+		"""
+		Converts a configuration input to a stream of bytes
+		"""
+		if length is None:
+			length = 0
+
+		confBytes = bytearray(conf)
+		if inputs is not None: # isinstance(inputs, float) or isinstance(inputs, int) or inputs:
+			valueBytes = self.__toByteArray(inputs, length)
+			return confBytes+valueBytes
+		else:
+			return confBytes
+
+	def serializeConfigBin(self, conf, inputs):
+		"""
+		Converts a configuration input, together with a binary payload input to a stream of bytes
+		"""
+		confBytes = bytearray(conf) + bytearray(inputs)
+		return confBytes
+
+class Interface():
+	"""
+	Interface prototype for extension with special interface functions
+	"""
+	def __init__(self, functionality):
+		super().__init__()
+
+		self.functionality = functionality
+		self.packager = Packager()
+	
+	def send(self, keys, *args):
+		"""
+		Generic sending function
+		"""
+		command = self.functionality.keyList.walkKeychain(keys)
+		return self.packager.serializeConfig(command, *args)
+
+	def sendBinary(self, keys, binary):
+		command = self.functionality.keyList.walkKeychain(keys)
+		return self.packager.serializeConfigBin(command, binary)
+
+	def sendDouble(self, keys, value):
+		"""
+		Send the platform keys field with a float value
+		"""
+		return self.send(keys, float(value), 8)
+
+	def sendInt(self, keys, value):
+		"""
+		Send the platform keys field with an integer value
+		"""
+		return self.send(keys, int(value), 4)
+
+class __Extension__():
+	"""
+	Base class for different platform modes
+	"""
+	def __init__(self, child, platform, configHandler, extName, debug = None):
+		# Connect variables
+		self.child = child
+		self.platform = platform
+		self.name = extName
+		self.functionality = self.platform.functionality
+		self.configHandler = configHandler
+
+		self.interface = Interface(self.functionality)
+
+		# Setup logging
+		if debug is None:
+			self.logger = logging.getLogger("general_logs.net.Extension")
+		else:
+			self.logger = logging.getLogger("general_logs.net.Extension@%s" % debug)
+
+		self.logger.setLevel(logging.DEBUG)
diff --git a/controlPlatform/extensions/baseband.py b/controlPlatform/extensions/baseband.py
new file mode 100644
index 0000000000000000000000000000000000000000..de3e9892345f6b0775312af77020c758d83abb1c
--- /dev/null
+++ b/controlPlatform/extensions/baseband.py
@@ -0,0 +1,23 @@
+from ..extension import __Extension__
+
+class Baseband(__Extension__):
+	"""
+	Extends a platform with baseband control functions
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Baseband")
+
+	def setStageLevel(self, level, stage):
+		"""
+		Sets baseband level for a certain stage
+		"""
+		self.configHandler.communicate((self.interface.sendDouble(["CONFIG", "EXTERNAL", "BB", stage], level)))
+
+	def setLevels(self, **levels):
+		"""
+		Sets baseband levels on a platform
+		"""
+		print("Set baseband levels on %s." % self.platform.name)
+
+		for stage in levels:
+			self.setStageLevel(levels[stage], stage)
\ No newline at end of file
diff --git a/controlPlatform/extensions/basic.py b/controlPlatform/extensions/basic.py
new file mode 100644
index 0000000000000000000000000000000000000000..f85a3cb984c9d138026246cdf2c8976be2ca9f45
--- /dev/null
+++ b/controlPlatform/extensions/basic.py
@@ -0,0 +1,151 @@
+from ..extension import __Extension__
+
+
+class Basic(__Extension__):
+    """
+    No mode is yet discovered for this platform
+    """
+
+    def __init__(self, platform, configHandler, family):
+        super().__init__(self, platform, configHandler, "Basic")
+
+        # The family is used for resolving properties of a platform, based on its unique identifier
+        self.family = family
+
+        # Unique identifier, e.g. MAC address
+        self.uuid = None
+
+        # A color code for this platform
+        self.colorCode = None
+
+        # Unique name, e.g. Niko
+        self.uname = None
+
+        # Type of this platform
+        self.platformType = None
+
+        # Family member. The name and position of this platform within the framework
+        self.member = None
+
+    def informIndex(self, index):
+        """
+        Informs a platform about its position in the array by index. This is mostly
+        relevant for transmitters that select a trigger impulse in the burst of triggers by index
+        """
+        try:
+            self.configHandler.communicate(self.interface.sendInt(
+                ["CONFIG", "SYS", "IDX"], index))
+
+        except AttributeError:
+            # This platform has no index, since it has no position
+            pass
+
+    def informRxCount(self, rx_cnt):
+        """
+        Informs a platform about total number of receivers
+        """
+        self.configHandler.communicate(self.interface.sendInt(
+            ["CONFIG", "SYS", "EXTERNAL", "SYS_RX_CNT"], rx_cnt))
+
+    def informTxCount(self, tx_cnt):
+        """
+        Informs a platform about total number of receivers
+        """
+        self.configHandler.communicate(self.interface.sendInt(
+            ["CONFIG", "SYS", "EXTERNAL", "SYS_TX_CNT"], tx_cnt))
+
+    def reset(self):
+        """
+        Sends a soft reset signal to the platform
+        """
+        print("Reset %s to bootloader." % self.platform.name)
+        self.configHandler.communicate(self.interface.send(["REQUEST", "RST"]))
+
+    def scanTest(self):
+        """
+        Connects to the platform for testing
+        """
+        return self.configHandler.testconn()
+
+    def getType(self):
+        """
+        Scans the connected platform for its type, if there is a platform at the specified address
+        """
+        # Ask platform for its type
+        platformType = self.configHandler.communicate(
+            self.interface.send(["REQUEST", "TYPE", "NAME"]))
+
+        # hello!
+        return platformType.pop()
+
+    def getSecondaryType(self):
+        """
+        Scans the connected platform for its secondary type, if there is a platform at the specified address
+        """
+        # Ask platform for its secondary type
+        secondaryType = self.configHandler.communicate(
+            self.interface.send(["REQUEST", "TYPE", "EXTENSION"]))
+
+        # hello!
+        return secondaryType.pop()
+
+    def getId(self):
+        """
+        Asks for platform unique identifier
+        """
+
+        # Extracts the unique id from the network handler
+        uuid = self.configHandler.communicate(
+            self.interface.send(["REQUEST", "TYPE", "UUID"]), sections=[("uint8", None)])
+
+        # Convert the uuid to a string for display and storage, byte by byte
+        uuidStr = '0x'
+
+        for field in uuid:
+            uuidStr = '%s%02x' % (uuidStr, field)
+
+        return uuidStr
+
+    def learnName(self):
+        """
+        This platform now learns its own name and properties and stores it
+        """
+        self.member = self.family.getMemberByUuid(self.uuid)
+
+        # Store platform position as a top level property for later sorting
+        if self.member is not None:
+            # Platform is known
+            self.platform.pos = self.member.position
+            self.platform.name = self.member.name
+
+    def scan(self):
+        """
+        Scan for this platform on the network
+        Return object ID for the task
+        """
+        self.platform.exists = self.scanTest()
+
+        if self.platform.exists:
+            self.identify()
+
+        return self.platform
+
+    def informIndex(self):
+        """
+        Inform platform of its index
+        """
+        try:
+            self.informIndex(self.platform.idx)
+        except:
+            # Only inform platforms that have an index.
+            pass
+
+    def identify(self):
+        """
+        Extracts general information from platform, as well as uuid/name
+        """
+        self.platformType = self.getType()
+        self.platformSecondaryType = self.getSecondaryType()
+        self.uuid = self.getId()
+
+        self.learnName()
diff --git a/controlPlatform/extensions/boot.py b/controlPlatform/extensions/boot.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4c7ec2481c1411b80ce0c94c49e996399cc6c89
--- /dev/null
+++ b/controlPlatform/extensions/boot.py
@@ -0,0 +1,30 @@
+from ..extension import __Extension__
+
+class Boot(__Extension__):
+	"""
+	Extends a platform by the boot mode
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Boot")
+
+	def flashErase(self):
+		"""
+		Erase the flash on the connected platform
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "FLASH", "ERASE"]))
+
+	def flashWrite(self, data):
+		"""
+		Erase the flash on the connected platform
+		"""
+		self.configHandler.communicate(self.interface.sendBinary(["CONFIG", "FLASH", "WRITE"], data))
+
+	def flash(self, data):
+		print("Flashing %s." % self.platform.name)
+		self.flashErase()
+		self.flashWrite(data)
+		self.run()
+
+	def run(self):
+		print("Run flash on %s." % self.platform.name)
+		self.configHandler.communicate(self.interface.send(["CONFIG", "FLASH", "RESET"]))
\ No newline at end of file
diff --git a/controlPlatform/extensions/calibrator.py b/controlPlatform/extensions/calibrator.py
new file mode 100644
index 0000000000000000000000000000000000000000..c86083370ab0a4b3e3bd530f6a1c8c5a58dd9231
--- /dev/null
+++ b/controlPlatform/extensions/calibrator.py
@@ -0,0 +1,8 @@
+from ..extension import __Extension__
+
+class Calibrator(__Extension__):
+	"""
+	Extends a platform by the "Calibrator" mode
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Calibrator")
diff --git a/controlPlatform/extensions/central.py b/controlPlatform/extensions/central.py
new file mode 100644
index 0000000000000000000000000000000000000000..824e1192255ea4f2155ff1e88c1af72c08edc8f3
--- /dev/null
+++ b/controlPlatform/extensions/central.py
@@ -0,0 +1,8 @@
+from ..extension import __Extension__
+
+class Central(__Extension__):
+	"""
+	Extends a platform by the "Central" mode
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Central")
diff --git a/controlPlatform/extensions/dds.py b/controlPlatform/extensions/dds.py
new file mode 100644
index 0000000000000000000000000000000000000000..d4375c767a810f3fdbc1c63272c0abfdaa62b597
--- /dev/null
+++ b/controlPlatform/extensions/dds.py
@@ -0,0 +1,14 @@
+from ..extension import __Extension__
+
+class Dds(__Extension__):
+	"""
+	Extends a platform with "Dds" functionality
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "DDS")
+
+	def configure(self):
+		"""
+		Signal to the DDS platform that configuration is finished and that DDS can now be programmed 
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "EXTERNAL", "DDS", "FINISHED"]))
diff --git a/controlPlatform/extensions/fmcw.py b/controlPlatform/extensions/fmcw.py
new file mode 100644
index 0000000000000000000000000000000000000000..56a5836e4d931b762ad1c711378473a59a545d6e
--- /dev/null
+++ b/controlPlatform/extensions/fmcw.py
@@ -0,0 +1,67 @@
+from ..extension import __Extension__
+
+
+class Fmcw(__Extension__):
+    """
+    Extends a platform with "Fmcw" functionality
+    """
+
+    def __init__(self, platform, configHandler):
+        super().__init__(self, platform, configHandler, "FMCW")
+
+    def fmcwConfigBandwidth(self, bandwidth):
+        """
+        Program chirp bandwidth
+        """
+        self.configHandler.communicate(self.interface.sendDouble(
+            ["CONFIG", "EXTERNAL", "FMCW", "CHIRP_BANDWIDTH"], bandwidth))
+
+    def fmcwConfigFrequency(self, startFreq):
+        """
+        Program starting frequency of the chirp
+        """
+        self.configHandler.communicate(
+            self.interface.sendDouble(["CONFIG", "EXTERNAL", "FMCW", "CHIRP_BASE_F"], startFreq))
+
+    def fmcwConfigOffsetFrequency(self, offsetFreq):
+        """
+        Program starting frequency of the chirp
+        """
+        self.configHandler.communicate(self.interface.sendDouble(
+            ["CONFIG", "EXTERNAL", "FMCW", "CHIRP_OFF_F"], offsetFreq))
+
+    def fmcwConfigHopFrequency(self, hopFreq):
+        """
+        Program hopping frequency between chirps
+        """
+        self.configHandler.communicate(self.interface.sendDouble(
+            ["CONFIG", "EXTERNAL", "FMCW", "CHIRP_HOP_F"], hopFreq))
+
+    def fmcwConfigDuration(self, duration):
+        """
+        Program duration of the chirp
+        """
+        self.configHandler.communicate(self.interface.sendDouble(
+            ["CONFIG", "EXTERNAL", "FMCW", "CHIRP_DURATION"], duration))
+
+    def fmcwConfigSamplingDelay(self, duration):
+        """
+        Program delay after which amplifier switches on and starts to transmit (compensation)
+        """
+        self.configHandler.communicate(self.interface.sendDouble(
+            ["CONFIG", "EXTERNAL", "FMCW", "TXDELAY"], duration))
+
+    def configure(self, bw, duration, fc, foffset=0, fhop=0, samplingDelay=0):
+        """
+        Configures the FMCW settings on the platform
+        """
+
+        print("Configure FMCW on %s." % self.platform.name)
+
+        # Transmit individual configuration settings
+        self.fmcwConfigBandwidth(bw)
+        self.fmcwConfigFrequency(fc)
+        self.fmcwConfigOffsetFrequency(foffset)
+        self.fmcwConfigHopFrequency(fhop)
+        self.fmcwConfigDuration(duration)
+        self.fmcwConfigSamplingDelay(samplingDelay)
diff --git a/controlPlatform/extensions/pll.py b/controlPlatform/extensions/pll.py
new file mode 100644
index 0000000000000000000000000000000000000000..40564d843151696b75a69cda37dad0eb45ff8462
--- /dev/null
+++ b/controlPlatform/extensions/pll.py
@@ -0,0 +1,15 @@
+from ..extension import __Extension__
+
+class Pll(__Extension__):
+	"""
+	Extends a platform with "Pll" functionality
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "PLL")
+
+	def configure(self):
+		"""
+		Signal to the PLL platform that configuration is finished and that PLL can now be programmed 
+		"""
+		self.handler.communicate(
+			self.interface.send(["CONFIG", "EXTERNAL", "PLL", "FINISHED"]))
\ No newline at end of file
diff --git a/controlPlatform/extensions/radar.py b/controlPlatform/extensions/radar.py
new file mode 100644
index 0000000000000000000000000000000000000000..b142fec38b9264bb8fce3bcd660b364886393d9b
--- /dev/null
+++ b/controlPlatform/extensions/radar.py
@@ -0,0 +1,31 @@
+from ..extension import __Extension__
+
+class Radar(__Extension__):
+	"""
+	Extends a platform with "Radar" functionality
+	"""
+
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Radar")
+
+	def informRxCount(self, rxCount):
+		"""
+		Informs the platform about the total count of receivers
+		"""
+		self.configHandler.communicate(self.interface.sendInt(["CONFIG", "SYS", "EXTERNAL", "SYS_RX_CNT"], rxCount))
+
+	def informTxCount(self, txCount):
+		"""
+		Informs the platform about the total count of transmitters
+		"""
+		self.configHandler.communicate(self.interface.sendInt(["CONFIG", "SYS", "EXTERNAL", "SYS_TX_CNT"], txCount))
+
+	def configure(self, rxCnt, txCnt):
+		"""
+		Configures the Radar settings on the platform
+		"""
+		print("Configure radar system settings on %s." % self.platform.name)
+
+		# Transmit individual configuration settings
+		self.informRxCount(rxCnt)
+		self.informTxCount(txCnt)
diff --git a/controlPlatform/extensions/receiver.py b/controlPlatform/extensions/receiver.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a09a02cbc8626cf801b56469a167f4952b88d33
--- /dev/null
+++ b/controlPlatform/extensions/receiver.py
@@ -0,0 +1,8 @@
+from ..extension import __Extension__
+
+class Receiver(__Extension__):
+	"""
+	Extends a platform with the "Receiver" mode
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Receiver")
\ No newline at end of file
diff --git a/controlPlatform/extensions/sampler.py b/controlPlatform/extensions/sampler.py
new file mode 100644
index 0000000000000000000000000000000000000000..74c36e296dd7f70387d1d314ec189d03a6a28698
--- /dev/null
+++ b/controlPlatform/extensions/sampler.py
@@ -0,0 +1,71 @@
+from ..extension import __Extension__
+
+from networkUtilities import PlatformHandler
+import numpy as np
+
+class Sampler(__Extension__):
+	"""
+	Extends a platform with ADC sampling capability
+	"""
+
+	def __init__(self, platform, configHandler, dataHandler):
+		super().__init__(self, platform, configHandler, "Sampler")
+
+		self.configHandler = configHandler
+		self.dataHandler = dataHandler
+
+	def configDuration(self, duration):
+		"""
+		Program duration of the sampling
+		"""
+		self.configHandler.communicate(self.interface.sendDouble(["CONFIG", "SAMPLING", "DURATION"], duration))
+
+	def configFinished(self):
+		"""
+		Signal end of sampler configuration
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "SAMPLING", "FINISHED"]))
+
+	def start(self):
+		"""
+		Make ready for sampling! This connects to the platform and opens the connection. Platform starts sampling automatically.
+		"""
+		self.dataHandler.connect()
+
+	def stop(self):
+		"""
+		End sampling by disconnecting from the platform.
+		"""
+		self.dataHandler.disconnect()
+
+	def get(self):
+		"""
+		Single shot sampling and storage on this platform
+		"""
+		# Do the sampling
+		self.adcBitFormatString = "int16"
+		rawBlock = self.dataHandler.receive(leaveOpen=True, sections=[("uint32", 8), (self.adcBitFormatString, None)])
+
+		measurement = np.asarray(rawBlock)
+
+		measurementIndex = measurement[0]
+		errorCounter = measurement[1]
+		data = measurement[2:]
+
+		try:
+			result = ((data, self.platform.idx), measurementIndex, errorCounter)
+		except AttributeError:
+			result = ((data, 0), measurementIndex, errorCounter)
+
+		return result
+		
+	def configure(self, duration):
+		"""
+		Configures the sampling settings on the platform
+		"""
+
+		print("Configure Sampling on %s." % self.platform.name)
+
+		# Transmit individual configuration settings
+		self.configDuration(duration)
+		self.configFinished()
diff --git a/controlPlatform/extensions/transmitter.py b/controlPlatform/extensions/transmitter.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7ca8374a32f59cf50651f744203d98b479db6fd
--- /dev/null
+++ b/controlPlatform/extensions/transmitter.py
@@ -0,0 +1,8 @@
+from ..extension import __Extension__
+
+class Transmitter(__Extension__):
+	"""
+	Extends a platform with transmitter functions
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Transmitter")
diff --git a/controlPlatform/extensions/trigger.py b/controlPlatform/extensions/trigger.py
new file mode 100644
index 0000000000000000000000000000000000000000..268a78a2235d61ba08e0fec020d34e6bfc9d1247
--- /dev/null
+++ b/controlPlatform/extensions/trigger.py
@@ -0,0 +1,54 @@
+from ..extension import __Extension__
+
+class Trigger(__Extension__):
+	"""
+	Extends a platform with trigger functions
+	"""
+	def __init__(self, platform, configHandler):
+		super().__init__(self, platform, configHandler, "Trigger")
+
+	def force(self):
+		"""
+		Forces a trigger impulse in all receivers. This will be asynchronous
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "TRIGGER", "FORCE"]))
+
+	def start(self):
+		"""
+		Starts the trigger impulses (or burst) on the trigger board (central platform)
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "TRIGGER", "START"]))
+
+	def stop(self):
+		"""
+		Stops the trigger impulses. Also resets the frequency hopping counter.
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "TRIGGER", "STOP"]))
+
+	def burst(self, burst):
+		"""
+		Sets the burst count of trigger impulses
+		"""
+		self.configHandler.communicate(self.interface.sendInt(["CONFIG", "TRIGGER", "BURST"], burst))
+
+	def rate(self, rate):
+		"""
+		Sets a new trigger frequency on the trigger board
+		"""
+		self.configHandler.communicate(self.interface.sendDouble(["CONFIG", "TRIGGER", "RATE"], rate))
+
+	def finish(self):
+		"""
+		Triggers configuration on embedded hardware
+		"""
+		self.configHandler.communicate(self.interface.send(["CONFIG", "TRIGGER", "FINISHED"]))
+
+	def configure(self, rate = 1, burst = 1):
+		"""
+		Configure periodic trigger
+		"""
+		print("Configure periodic trigger on %s." % self.platform.name)
+
+		self.burst(burst)
+		self.rate(rate)
+		self.finish()
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..85d3f4d3907b7b44a13cd584c2c36e254e6736f1
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Note: To use the 'upload' functionality of this file, you must:
+#   $ pipenv install twine --dev
+
+import io
+import os
+import sys
+from shutil import rmtree
+
+from setuptools import find_packages, setup, Command
+
+# Package meta-data.
+NAME = 'controlPlatform'
+DESCRIPTION = 'Provides defenitions and extensions for the digital sampling platform.'
+URL = ''
+EMAIL = 'adrian@figueroa.eu'
+AUTHOR = 'Adrian Figueroa'
+REQUIRES_PYTHON = '>=3.6.0'
+VERSION = '0.1.0'
+
+# What packages are required for this module to be executed?
+REQUIRED = [
+    'extensionObject',
+	'networkUtilities',
+    'numpy'
+]
+
+# What packages are optional?
+EXTRAS = {
+}
+
+# The rest you shouldn't have to touch too much :)
+# ------------------------------------------------
+# Except, perhaps the License and Trove Classifiers!
+# If you do change the License, remember to change the Trove Classifier for that!
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+# Import the README and use it as the long-description.
+# Note: this will only work if 'README.md' is present in your MANIFEST.in file!
+try:
+    with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
+        long_description = '\n' + f.read()
+except FileNotFoundError:
+    long_description = DESCRIPTION
+
+# Load the package's __version__.py module as a dictionary.
+about = {}
+if not VERSION:
+    project_slug = NAME.lower().replace("-", "_").replace(" ", "_")
+    with open(os.path.join(here, project_slug, '__version__.py')) as f:
+        exec(f.read(), about)
+else:
+    about['__version__'] = VERSION
+
+
+class UploadCommand(Command):
+    """Support setup.py upload."""
+
+    description = 'Build and publish the package.'
+    user_options = []
+
+    @staticmethod
+    def status(s):
+        """Prints things in bold."""
+        print('\033[1m{0}\033[0m'.format(s))
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        try:
+            self.status('Removing previous builds…')
+            rmtree(os.path.join(here, 'dist'))
+        except OSError:
+            pass
+
+        self.status('Building Source and Wheel (universal) distribution…')
+        os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable))
+
+        self.status('Uploading the package to PyPI via Twine…')
+        os.system('twine upload dist/*')
+
+        self.status('Pushing git tags…')
+        os.system('git tag v{0}'.format(about['__version__']))
+        os.system('git push --tags')
+
+        sys.exit()
+
+
+# Where the magic happens:
+setup(
+    name=NAME,
+    version=about['__version__'],
+    description=DESCRIPTION,
+    long_description=long_description,
+    long_description_content_type='text/markdown',
+    author=AUTHOR,
+    author_email=EMAIL,
+    python_requires=REQUIRES_PYTHON,
+    url=URL,
+    packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]),
+    # If your package is a single module, use this instead of 'packages':
+    # py_modules=['mypackage'],
+
+    # entry_points={
+    #     'console_scripts': ['mycli=mymodule:cli'],
+    # },
+    install_requires=REQUIRED,
+    extras_require=EXTRAS,
+    include_package_data=True,
+    license='MIT',
+    classifiers=[
+        # Trove classifiers
+        # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
+        'License :: OSI Approved :: MIT License',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: Implementation :: CPython',
+        'Programming Language :: Python :: Implementation :: PyPy'
+    ],
+    # $ setup.py publish support.
+    cmdclass={
+        'upload': UploadCommand,
+    },
+)