{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "e19197ba", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "import matplotlib.pyplot as plt\n", "import matplotlib.image as mpimg" ] }, { "cell_type": "markdown", "id": "ea1a7a45", "metadata": {}, "source": [ "# Simple 2 tap fading" ] }, { "cell_type": "code", "execution_count": 2, "id": "4465dcd9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "nsamples = 200\n", "samp_rate = 32e3\n", "\n", "# QPSK modulation\n", "samp_per_sym = 4\n", "symbol_map = {\n", " 0: 1 + 1j,\n", " 1: -1 + 1j,\n", " 2: -1 - 1j,\n", " 3: 1 - 1j,\n", "}\n", "\n", "# generate random data for testing\n", "data = np.random.randint(low=0, high=4, size=nsamples)\n", "\n", "# modulate and add AWGN\n", "noise = np.random.normal(0, .03, size=nsamples) + 1j * np.random.normal(0, .03, size=nsamples)\n", "sig = np.array(list(map(lambda v: symbol_map[v], data))) + noise\n", "\n", "# add 2 tap frequency selective channel\n", "delay = np.zeros(5 * samp_per_sym)\n", "one = np.array([1])\n", "taps = np.concatenate([one, delay, .2 * one])\n", "\n", "# apply channel\n", "sig_fading = np.convolve(sig, taps)\n", "\n", "# plot figure\n", "fig = plt.figure()\n", "plt.scatter(sig_fading.real, sig_fading.imag)" ] }, { "cell_type": "code", "execution_count": null, "id": "db9b381c", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.2" } }, "nbformat": 4, "nbformat_minor": 5 }