{ "cells": [ { "cell_type": "markdown", "id": "efc46b98-fcfb-4a29-a48e-feadc09bb093", "metadata": {}, "source": [ "# TDL Channel\n", "This notebook shows how to use a TDL channel in time and frequency domains." ] }, { "cell_type": "code", "execution_count": 1, "id": "95faa819-986f-498a-8204-2a372fb70c70", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import scipy.io\n", "import time\n", "\n", "from neoradium import Carrier, Modem, TdlChannel, Grid, random\n", "from neoradium.utils import getNmse" ] }, { "cell_type": "code", "execution_count": 2, "id": "6852bf87-ada1-4c5b-a7c4-b75a100d638d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape of Resource Grid: (8, 14, 300)\n", "Shape of Waveform: (8, 30720)\n" ] } ], "source": [ "# Create a valid random grid\n", "random.setSeed(123) # Make results reproducible\n", "carrier = Carrier(startRb=0, numRbs=25, spacing=15) # Carrier 25 Resource Blocks, 15KHz subcarrier spacing\n", "bwp = carrier.curBwp # The only bandwidth part in the carrier\n", "txGrid = bwp.createGrid(numPlanes=8) # Create an empty resource grid\n", "\n", "stats = txGrid.getStats() # Get statistics about the grid\n", "modem = Modem(\"16QAM\") # Using 16QAM modulation\n", "numRandomBits = stats['UNASSIGNED']*modem.qm # Total number of bits available in the resource grid\n", "\n", "bits = random.bits(numRandomBits) # Create random bits\n", "symbols = modem.modulate(bits) # Modulate the bits to get symbols\n", "\n", "indexes = txGrid.getReIndexes(\"UNASSIGNED\") # Indexes of the \"UNASSIGNED\" resources\n", "txGrid[indexes] = symbols # Put symbols in the resource grid\n", "\n", "txWaveform = txGrid.ofdmModulate() # OFDM-Modulate the resource grid to get a waveform\n", "\n", "print(\"Shape of Resource Grid:\",txGrid.shape)\n", "print(\"Shape of Waveform: \",txWaveform.shape)\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "d9fcd860-1480-4c68-9b5b-62d14db2b6e4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "TDL-D Channel Properties:\n", " carrierFreq: 4 GHz\n", " normalizeGains: True\n", " normalizeOutput: True\n", " txDir: Downlink\n", " filterLen: 16 samples\n", " delayQuantSize: 64\n", " stopBandAtten: 80 db\n", " dopplerShift: 50 Hz\n", " coherenceTime: 8.463 milliseconds\n", " delaySpread: 30 ns\n", " pathDelays (ns): 0.0000 1.0500 18.360 40.890 42.150 54.120 77.880 53.250 121.26 238.11\n", " 282.72 291.24 375.75\n", " pathPowers (db): -0.001 -18.80 -21.00 -22.80 -17.90 -20.10 -21.90 -22.90 -27.80 -23.60\n", " -24.80 -30.00 -27.70\n", " hasLOS: True\n", " kFactorLos (db): 13.300\n", " rxAntennaCount: 2\n", " txAntennaCount: 8\n", " mimoCorrelation: Medium\n", " polarization: CoPolar\n", " sosType: GMEDS1\n", " sosNumSins: 32\n", "\n" ] } ], "source": [ "# Create a TDL-D channel model with 4GHz carrier frequency, and 50Hz doppler shift\n", "channel = TdlChannel(bwp, 'D', carrierFreq=4e9, dopplerShift=50,\n", " txAntennaCount=8, rxAntennaCount=2, mimoCorrelation='Medium')\n", "print(channel)" ] }, { "cell_type": "code", "execution_count": 4, "id": "17c876c9-9ec1-47af-a4c5-09dcbc143ade", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Time to apply channel in Freq. Domain: 0.004817008972167969\n" ] } ], "source": [ "# Apply the channel in Frequency Domain:\n", "t0 =time.time()\n", "channelMatrix = channel.getChannelMatrix()\n", "rxGridF = txGrid.applyChannel(channelMatrix)\n", "t1 =time.time()\n", "print(\"Time to apply channel in Freq. Domain:\", t1-t0)" ] }, { "cell_type": "code", "execution_count": 5, "id": "f0d833cd-82f7-4721-a81a-941ca7e980f2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Time to apply channel in Time Domain: 0.09486007690429688\n", "NMSE between the rxGrid in Time and Freq. domains: 6.26924445685763e-17\n" ] } ], "source": [ "# Applying the channel in time domain and demodulate to get a received resource grid (rxGrid)\n", "t0 =time.time()\n", "maxDelay = channel.getMaxDelay() # Calculate the channel's max delay\n", "paddedTxWaveform = txWaveform.pad(maxDelay) # Pad the waveform with zeros\n", "rxWaveform = channel.applyToSignal(paddedTxWaveform) # Apply the channel to the waveform\n", "offset = channel.getTimingOffset() # Get the timing offset for synchronization\n", "syncedWaveform = rxWaveform.sync(offset) # Synchronization\n", "rxGridT = Grid.ofdmDemodulate(bwp, syncedWaveform) # OFDM-demodulation\n", "t1 =time.time()\n", "print(\"Time to apply channel in Time Domain:\", t1-t0)\n", "print(\"NMSE between the rxGrid in Time and Freq. domains: \", getNmse(rxGridT.grid,rxGridF.grid)) \n" ] }, { "cell_type": "code", "execution_count": null, "id": "3b83e1e2-a7e9-4439-8712-82fb67ca0b3f", "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.6" } }, "nbformat": 4, "nbformat_minor": 5 }