Commit c896b1b6 authored by Smail Bachir's avatar Smail Bachir Committed by Thomas Gambier

Small improvements

parent de5b8855
...@@ -4,7 +4,7 @@ Pre-Distortion for Linearization of RF power amplifier in python using ADALM PLU ...@@ -4,7 +4,7 @@ Pre-Distortion for Linearization of RF power amplifier in python using ADALM PLU
This program is released under GPL version 3 or any later version. This program is released under GPL version 3 or any later version.
## Overview ## Overview
The pyPlutoDPD is a python implementation of Digital Pre-Distortion, a most used technique to linearize the distortions introiduced by the RF Power Amplifiers. The pyPlutoDPD is a python implementation of Digital Pre-Distortion, a most used technique to linearize the distortions introduced by the RF Power Amplifiers.
This has been developed under python by: </br> This has been developed under python by: </br>
- Smail Bachir, University of Poitiers, XLIM-Laboratory UMR-CNRS 7252 - Smail Bachir, University of Poitiers, XLIM-Laboratory UMR-CNRS 7252
...@@ -17,13 +17,29 @@ in collaboration with: ...@@ -17,13 +17,29 @@ in collaboration with:
LMS Algorithm running with a polular ADALM-PlutoSDR has been implemneted. LMS Algorithm running with a polular ADALM-PlutoSDR has been implemneted.
<b> Pre-requises </b> : pyPlutoDPD requires only free dependances : <b> Pre-requises </b> : pyPlutoDPD requires only free dependances :
- Python with packages : numpy, adi, matplotlib, scipy - Python with packages : numpy, adi, matplotlib, scipy, time
- Install PlutoSDR in Python : see https://pysdr.org/content/pluto.html - Install PlutoSDR in Python : see https://pysdr.org/content/pluto.html
- Cheap board : Adalm PlutoSDR - Cheap board : Adalm PlutoSDR
<b> Setup </b> : pyPlutoDPD can be used with two configuations <b> Setup </b> : pyPlutoDPD can be used with two configuations
1. Minimale configuration with only ADALM-Pluto SDR connected to himself (SMA wire bettween TX and RX). This allows to test the program and see the steps. 1. For initial test with only ADALM-Pluto connected to himself (SMA wire bettween TX and RX). This allows to test the program and see the steps.
2. Configuration with DUT (Device Under Test) : Here, insert your RF-PA bettween TX and RX. In our case, we linearize a RF PA of .....
<img src="./img/pluto_alone.png" width="500" />
2. Configuration with DUT (Device Under Test) : Here, insert your RF-PA bettween TX and RX. In our case, we linearize an asymmetrical 10W/2-Stage Doherty Amplifier Module (GaN on SiC Technology)
<img src="./img/pluto_dut.png" width="500" />
## Setting parameters
- fileRx : The file containing baseband samples (in .bin, .mat, .csv, .txt, ...)
- sample_rate : sampling frequency (in MHz). Here 61.44 MHz
- osf : the used Over-Sampling Factor for I/Q samples. Here osf = 3
- freq : RF frequency (in Hz). Here 3650 MHz
- initialGain : ADALM-Pluto TX gain (in dB. Here -73dB for board safety
- sdr.rx_hardwaregain_chan0 : ADALM-Pluto RX gain (in dB)
- [Ka, La, Kb, Lb, Mb, Kc, Lc, Mc] : GMP model orders. Here [6, 2, 2, 2, 1, 0, 1, 1]
# Main program # Main program
...@@ -39,8 +55,6 @@ from scipy.signal import get_window ...@@ -39,8 +55,6 @@ from scipy.signal import get_window
from scipy.fft import fft, fftshift from scipy.fft import fft, fftshift
from scipy import signal from scipy import signal
import time import time
start = time.time() # start time to measure the execution time
``` ```
Load the used functions located in the ./commonFunctions.py Load the used functions located in the ./commonFunctions.py
...@@ -55,12 +69,12 @@ from commonFunctions import * # XLIM used functions ...@@ -55,12 +69,12 @@ from commonFunctions import * # XLIM used functions
### Transmit original samples ### Transmit original samples
Load transmitted samples en .bin format Load transmitted samples en .bin format
The preambule samples are used for synchronization The preambule samples are used for synchronization
You can use "lte-5G/BW-10MHz with 61.44MHz of sampling rate" or "WLAN/BW-10MHz with 60MHz of sampling sate" You can use "lte-5G/BW-20MHz with 61.44MHz of sampling rate" or "WLAN/BW-20MHz with 60MHz of sampling sate"
```python ```python
# Read the frame # Read the frame
path = "" path = "./samples/"
osf = 3 osf = 3
filePreambule = "preambule_BW20osf" + str(osf) + "_single.bin" filePreambule = "preambule_BW20osf" + str(osf) + "_single.bin"
fileRx = "lteBW20osf" + str(osf) + "_single.bin" fileRx = "lteBW20osf" + str(osf) + "_single.bin"
...@@ -104,22 +118,22 @@ Config Tx and start transmitting ...@@ -104,22 +118,22 @@ Config Tx and start transmitting
freq = int(3650) freq = int(3650)
win_fft = 'flattop' # The used window for FFT ans spectrum plot win_fft = 'flattop' # The used window for FFT ans spectrum plot
initialGain = int(0) # Here, the initial gain of TX is set to the minimal value for safety initialGain = int(-73) # Here, the initial gain of TX is set to the minimal value for safety
sdr.tx_rf_bandwidth = int(sample_rate) # filter cutoff sdr.tx_rf_bandwidth = int(sample_rate) # filter cutoff
sdr.tx_lo = freq*10**6 sdr.tx_lo = freq*10**6
sdr.tx_hardwaregain_chan0 = initialGain # sdr.tx_hardwaregain_chan0 = initialGain #
sdr.tx_destroy_buffer() # Stop transmitting for safe sdr.tx_destroy_buffer() # Stop transmitting for safe
sdr.tx_cyclic_buffer = True # Enable cyclic buffers sdr.tx_cyclic_buffer = True # Enable cyclic buffers
safetyGain = float(0) # set your tx gain limitation according to your DUT safetyGain = float(-10) # set your tx gain limitation according to your DUT
sdr.tx(samples) # start transmitting sdr.tx(samples) # start transmitting
``` ```
Loop for tx_gain monitoring in real time # Loop for tx_gain monitoring in real time
```python ```python
valid = False valid = True
while (valid): while (valid):
valid = input("1 to set txGain || 0 to compute DPD : ") valid = input("1 to set txGain || 0 to compute DPD : ")
valid = bool(int(valid)) valid = bool(int(valid))
...@@ -130,8 +144,15 @@ while (valid): ...@@ -130,8 +144,15 @@ while (valid):
sdr.tx_hardwaregain_chan0 = gain sdr.tx_hardwaregain_chan0 = gain
else: else:
sdr.tx_hardwaregain_chan0 = safetyGain sdr.tx_hardwaregain_chan0 = safetyGain
start = time.time() # start time to measure the execution time just befor tranmitting
``` ```
1 to set txGain || 0 to compute DPD : 1
enter new txGain (Actual txGain = -73) : 0
1 to set txGain || 0 to compute DPD : 0
### Receive the original samples ### Receive the original samples
...@@ -140,7 +161,7 @@ sdr.rx_lo = sdr.tx_lo ...@@ -140,7 +161,7 @@ sdr.rx_lo = sdr.tx_lo
sdr.rx_rf_bandwidth = sdr.tx_rf_bandwidth sdr.rx_rf_bandwidth = sdr.tx_rf_bandwidth
sdr.rx_buffer_size = 3*num_samps # 3 times to capture one sequence sdr.rx_buffer_size = 3*num_samps # 3 times to capture one sequence
sdr.gain_control_mode_chan0 = 'manual' sdr.gain_control_mode_chan0 = 'manual'
sdr.rx_hardwaregain_chan0 = 8 # set the receive gain, but be careful not to saturate the ADC sdr.rx_hardwaregain_chan0 = 15 # set the receive gain, but be careful not to saturate the ADC
``` ```
Clear buffer just to be safe Clear buffer just to be safe
...@@ -158,10 +179,10 @@ Receive samples ...@@ -158,10 +179,10 @@ Receive samples
rx_samples = sdr.rx() rx_samples = sdr.rx()
avg_pwr = np.mean(np.abs(rx_samples/coeff)**2) avg_pwr = np.mean(np.abs(rx_samples/coeff)**2)
avg_pwr_dB = round(10*np.log10(avg_pwr),2) avg_pwr_dB = round(10*np.log10(avg_pwr),2)
print("check_rx = ", avg_pwr_dB, ": Best in -30 +/- 5. Else, adjust the rx_hardwaregain") print("check_rx = ", avg_pwr_dB, ": Best in -30 +/- 3. Else, adjust the rx_hardwaregain")
``` ```
check_rx = -29.38 : Best in -30 +/- 5. Else, adjust the rx_hardwaregain check_rx = -32.49 : Best in -30 +/- 3. Else, adjust the rx_hardwaregain
Synchronization and coarse phase correction using the preambule (zeroing AM/PM) Synchronization and coarse phase correction using the preambule (zeroing AM/PM)
...@@ -191,9 +212,7 @@ plt.legend(['Original signal']) ...@@ -191,9 +212,7 @@ plt.legend(['Original signal'])
plt.show() plt.show()
``` ```
<img src="./img/spectre_without.png" width="500" />
![png](img/output_26_0.png)
...@@ -205,9 +224,7 @@ amam_ampm_plot(paIn, paOut) ...@@ -205,9 +224,7 @@ amam_ampm_plot(paIn, paOut)
plt.show() plt.show()
``` ```
<img src="./img/am_pm_without.png" width="500" />
![png](img/output_28_0.png)
...@@ -223,7 +240,7 @@ $y_{dpd}(n)$ : dpd output (complex envelope) ...@@ -223,7 +240,7 @@ $y_{dpd}(n)$ : dpd output (complex envelope)
```python ```python
dpdModel = {'fs': sample_rate} dpdModel = {'fs': sample_rate}
[Ka, La, Kb, Lb, Mb, Kc, Lc, Mc] = [7, 1, 0, 1, 1, 0, 1, 1] # set the dpd orders and memory depths [Ka, La, Kb, Lb, Mb, Kc, Lc, Mc] = [6, 2, 2, 2, 1, 0, 1, 1] # set the dpd orders and memory depths
dpdModel['parameters'] = {'Ka':Ka, 'La':La, 'Kb':Kb, 'Lb':Lb, 'Mb':Mb, 'Kc':Kc, 'Lc':Lc, 'Mc':Mc}; dpdModel['parameters'] = {'Ka':Ka, 'La':La, 'Kb':Kb, 'Lb':Lb, 'Mb':Mb, 'Kc':Kc, 'Lc':Lc, 'Mc':Mc};
gainATT = 1 gainATT = 1
...@@ -239,8 +256,8 @@ print("dpd tx-power = ", txPower, " dBm") ...@@ -239,8 +256,8 @@ print("dpd tx-power = ", txPower, " dBm")
dpdOutput *= coeff # scaling for ADALM-Pluto dpdOutput *= coeff # scaling for ADALM-Pluto
``` ```
nmse of identification : -32.15 dB nmse of identification : -32.41 dB
dpd tx-power = -11.255 dBm dpd tx-power = -10.506 dBm
## Transmission with DPD ## Transmission with DPD
...@@ -253,8 +270,9 @@ sdr.tx_destroy_buffer() # Stop transmitting for safe ...@@ -253,8 +270,9 @@ sdr.tx_destroy_buffer() # Stop transmitting for safe
sdr.tx_cyclic_buffer = True # Enable cyclic buffers sdr.tx_cyclic_buffer = True # Enable cyclic buffers
sdr.tx(dpdOutput) # start transmitting with DPD sdr.tx(dpdOutput) # start transmitting with DPD
end = time.time() # end of DPD computation
valid = False valid = True
while (valid): while (valid):
valid = input("1 to set txGain || 0 to compute DPD : ") valid = input("1 to set txGain || 0 to compute DPD : ")
valid = bool(int(valid)) valid = bool(int(valid))
...@@ -270,6 +288,9 @@ while (valid): ...@@ -270,6 +288,9 @@ while (valid):
# np.savetxt('outfile.txt', rx_samples.view(complex)) # np.savetxt('outfile.txt', rx_samples.view(complex))
``` ```
1 to set txGain || 0 to compute DPD : 0
### Receive with DPD signal ### Receive with DPD signal
...@@ -280,7 +301,7 @@ avg_pwr_dB = round(10*np.log10(avg_pwr),2) ...@@ -280,7 +301,7 @@ avg_pwr_dB = round(10*np.log10(avg_pwr),2)
print("check_rx = ", avg_pwr_dB, ": Best in -30 +/- 5. Else, adjust the rx_hardwaregain") print("check_rx = ", avg_pwr_dB, ": Best in -30 +/- 5. Else, adjust the rx_hardwaregain")
``` ```
check_rx = -29.39 : Best in -30 +/- 5. Else, adjust the rx_hardwaregain check_rx = -32.48 : Best in -30 +/- 5. Else, adjust the rx_hardwaregain
Synchronization of input and output Synchronization of input and output
...@@ -300,18 +321,14 @@ Plot Linearized AM/AM and AM/PM ...@@ -300,18 +321,14 @@ Plot Linearized AM/AM and AM/PM
```python ```python
amam_ampm_plot(paIn, paLin) amam_ampm_plot(paIn, paLin)
plt.show() plt.show()
print("nmse after linearization : ", np.round(nmse(paIn, paLin), 2), " dB") #print("nmse after linearization : ", np.round(nmse(paIn, paLin), 2), " dB")
``` ```
<img src="./img/am_pm_with.png" width="500" />
![png](img/output_40_0.png)
nmse after linearization : -20.5 dB
```python ```python
plt.figure() plt.figure()
...@@ -337,7 +354,7 @@ plt.show() ...@@ -337,7 +354,7 @@ plt.show()
![png](img/output_41_0.png) ![png](img/output_42_0.png)
...@@ -353,9 +370,7 @@ plt.xlabel('Frequency (MHz)'); plt.ylabel('Spectrum'); plt.legend(['With DPD']) ...@@ -353,9 +370,7 @@ plt.xlabel('Frequency (MHz)'); plt.ylabel('Spectrum'); plt.legend(['With DPD'])
plt.show() plt.show()
``` ```
<img src="./img/spectre_with.png" width="500" />
![png](img/output_43_0.png)
...@@ -363,6 +378,7 @@ Stop transmitting ...@@ -363,6 +378,7 @@ Stop transmitting
```python ```python
sdr.tx_hardwaregain_chan0 = -73
sdr.tx_destroy_buffer() sdr.tx_destroy_buffer()
``` ```
...@@ -370,25 +386,10 @@ Print the DPD coefficients ...@@ -370,25 +386,10 @@ Print the DPD coefficients
```python ```python
end = time.time()
elapsed = end - start elapsed = end - start
print(f'Elapsed time : {elapsed:.2}ms') print(f'Elapsed time : {elapsed:.2}ms')
``` ```
Elapsed time : 3.5ms Elapsed time : 1.1ms
```python
for i in dpdModel['coefGMP']:
print(np.round(i,3))
```
(0.911+0.003j)
(-0.163-0.035j)
(0.934+0.218j)
(-2.078-0.554j)
(2.636+0.797j)
(-1.658-0.524j)
(0.414+0.105j)
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,25 +8,26 @@ ...@@ -8,25 +8,26 @@
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your # it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation. # option) any later version, as published by the Free Software Foundation.
# #
# You can also Link and Combine this program with other software covered by # You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source # the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding # Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other # source of such a combination shall include the source code for all other
# software used. # software used.
# #
# This program is distributed WITHOUT ANY WARRANTY; without even the implied # This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# #
# See COPYING file for full licensing terms. # See COPYING file for full licensing terms.
# #
############################################################################## ##############################################################################
# # pyPlutoDPD # # pyPlutoDPD
# Pre-Distortion for Linearization of RF power amplifier in python using ADALM PLUTO. # Pre-Distortion for Linearization of RF power amplifier in python using ADALM PLUTO.
# ## Overview # ## Overview
# The pyPlutoDPD is a python implementation of Digital Pre-Distortion, a most used technique to linearize the distortions introiduced by the RF Power Amplifiers. # The pyPlutoDPD is a python implementation of Digital Pre-Distortion, a most used technique to linearize the distortions introduced by the RF Power Amplifiers.
# #
# This has been developed under python by: # This has been developed under python by:
# - Smail Bachir, University of Poitiers, XLIM-Laboratory UMR-CNRS 7252 # - Smail Bachir, University of Poitiers, XLIM-Laboratory UMR-CNRS 7252
...@@ -39,22 +40,37 @@ ...@@ -39,22 +40,37 @@
# LMS Algorithm running with a polular ADALM-PlutoSDR has been implemneted. # LMS Algorithm running with a polular ADALM-PlutoSDR has been implemneted.
# #
# <b> Pre-requises </b> : pyPlutoDPD requires only free dependances : # <b> Pre-requises </b> : pyPlutoDPD requires only free dependances :
# - Python with packages : numpy, adi, matplotlib, scipy # - Python with packages : numpy, adi, matplotlib, scipy, time
# - Install PlutoSDR in Python : see https://pysdr.org/content/pluto.html # - Install PlutoSDR in Python : see https://pysdr.org/content/pluto.html
# - Cheap board : Adalm PlutoSDR # - Cheap board : Adalm PlutoSDR
# #
# <b> Setup </b> : pyPlutoDPD can be used with two configuations # <b> Setup </b> : pyPlutoDPD can be used with two configuations
# 1. Minimale configuration with only ADALM-Pluto SDR connected to himself (SMA wire bettween TX and RX). This allows to test the program and see the steps. # 1. For initial test with only ADALM-Pluto connected to himself (SMA wire bettween TX and RX). This allows to test the program and see the steps.
# 2. Configuration with DUT (Device Under Test) : Here, insert your RF-PA bettween TX and RX. In our case, we linearize a RF PA of ..... #
# <img src="./img/pluto_alone.png" width="500" />
#
#
# 2. Configuration with DUT (Device Under Test) : Here, insert your RF-PA bettween TX and RX. In our case, we linearize an asymmetrical 10W/2-Stage Doherty Amplifier Module (GaN on SiC Technology)
#
# <img src="./img/pluto_dut.png" width="500" />
#
# ## Setting parameters
# - fileRx : The file containing baseband samples (in .bin, .mat, .csv, .txt, ...)
# - sample_rate : sampling frequency (in MHz). Here 61.44 MHz
# - osf : the used Over-Sampling Factor for I/Q samples. Here osf = 3
# - freq : RF frequency (in Hz). Here 3650 MHz
# - initialGain : ADALM-Pluto TX gain (in dB. Here -73dB for board safety
# - sdr.rx_hardwaregain_chan0 : ADALM-Pluto RX gain (in dB)
# - [Ka, La, Kb, Lb, Mb, Kc, Lc, Mc] : GMP model orders. Here [6, 2, 2, 2, 1, 0, 1, 1]
# # Main program # # Main program
# ### Required packages # ### Required packages
# In[47]: # In[27]:
from commonFunctions import * # XLIM used functions
import numpy as np import numpy as np
import adi # API for Adalm-Pluto import adi # API for Adalm-Pluto
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
...@@ -64,12 +80,13 @@ from scipy.fft import fft, fftshift ...@@ -64,12 +80,13 @@ from scipy.fft import fft, fftshift
from scipy import signal from scipy import signal
import time import time
start = time.time() # start time to measure the execution time
# Load the used functions located in the ./commonFunctions.py # Load the used functions located in the ./commonFunctions.py
# In[48]: # In[28]:
from commonFunctions import * # XLIM used functions
# ## Transmission without DPD # ## Transmission without DPD
...@@ -77,13 +94,13 @@ start = time.time() # start time to measure the execution time ...@@ -77,13 +94,13 @@ start = time.time() # start time to measure the execution time
# ### Transmit original samples # ### Transmit original samples
# Load transmitted samples en .bin format # Load transmitted samples en .bin format
# The preambule samples are used for synchronization # The preambule samples are used for synchronization
# You can use "lte-5G/BW-10MHz with 61.44MHz of sampling rate" or "WLAN/BW-10MHz with 60MHz of sampling sate" # You can use "lte-5G/BW-20MHz with 61.44MHz of sampling rate" or "WLAN/BW-20MHz with 60MHz of sampling rate"
# In[49]: # In[29]:
# Read the frame # Read the frame
path = "" path = "./samples/"
osf = 3 osf = 3
filePreambule = "preambule_BW20osf" + str(osf) + "_single.bin" filePreambule = "preambule_BW20osf" + str(osf) + "_single.bin"
fileRx = "lteBW20osf" + str(osf) + "_single.bin" fileRx = "lteBW20osf" + str(osf) + "_single.bin"
...@@ -111,7 +128,7 @@ samples *= coeff ...@@ -111,7 +128,7 @@ samples *= coeff
# Connect the sdr pluto # Connect the sdr pluto
# In[50]: # In[30]:
sdr = adi.Pluto("ip:192.168.2.1") sdr = adi.Pluto("ip:192.168.2.1")
...@@ -120,30 +137,30 @@ sdr.sample_rate = sample_rate ...@@ -120,30 +137,30 @@ sdr.sample_rate = sample_rate
# Config Tx and start transmitting # Config Tx and start transmitting
# In[51]: # In[31]:
freq = int(3650) freq = int(3650)
win_fft = 'flattop' # The used window for FFT ans spectrum plot win_fft = 'flattop' # The used window for FFT ans spectrum plot
# Here, the initial gain of TX is set to the minimal value for safety # Here, the initial gain of TX is set to the minimal value for safety
initialGain = int(0) initialGain = int(-73)
sdr.tx_rf_bandwidth = int(sample_rate) # filter cutoff sdr.tx_rf_bandwidth = int(sample_rate) # filter cutoff
sdr.tx_lo = freq*10**6 sdr.tx_lo = freq*10**6
sdr.tx_hardwaregain_chan0 = initialGain sdr.tx_hardwaregain_chan0 = initialGain
sdr.tx_destroy_buffer() # Stop transmitting for safe sdr.tx_destroy_buffer() # Stop transmitting for safe
sdr.tx_cyclic_buffer = True # Enable cyclic buffers sdr.tx_cyclic_buffer = True # Enable cyclic buffers
safetyGain = float(0) # set your tx gain limitation according to your DUT safetyGain = float(-10) # set your tx gain limitation according to your DUT
sdr.tx(samples) # start transmitting sdr.tx(samples) # start transmitting
# Loop for tx_gain monitoring in real time # # Loop for tx_gain monitoring in real time
# In[52]: # In[32]:
valid = False valid = True
while (valid): while (valid):
valid = input("1 to set txGain || 0 to compute DPD : ") valid = input("1 to set txGain || 0 to compute DPD : ")
valid = bool(int(valid)) valid = bool(int(valid))
...@@ -156,10 +173,12 @@ while (valid): ...@@ -156,10 +173,12 @@ while (valid):
else: else:
sdr.tx_hardwaregain_chan0 = safetyGain sdr.tx_hardwaregain_chan0 = safetyGain
start = time.time() # start time to measure the execution time just befor tranmitting
# ### Receive the original samples # ### Receive the original samples
# In[53]: # In[33]:
sdr.rx_lo = sdr.tx_lo sdr.rx_lo = sdr.tx_lo
...@@ -167,12 +186,12 @@ sdr.rx_rf_bandwidth = sdr.tx_rf_bandwidth ...@@ -167,12 +186,12 @@ sdr.rx_rf_bandwidth = sdr.tx_rf_bandwidth
sdr.rx_buffer_size = 3*num_samps # 3 times to capture one sequence sdr.rx_buffer_size = 3*num_samps # 3 times to capture one sequence
sdr.gain_control_mode_chan0 = 'manual' sdr.gain_control_mode_chan0 = 'manual'
# set the receive gain, but be careful not to saturate the ADC # set the receive gain, but be careful not to saturate the ADC
sdr.rx_hardwaregain_chan0 = 8 sdr.rx_hardwaregain_chan0 = 15
# Clear buffer just to be safe # Clear buffer just to be safe
# In[54]: # In[34]:
for i in range(0, 10): for i in range(0, 10):
...@@ -181,26 +200,26 @@ for i in range(0, 10): ...@@ -181,26 +200,26 @@ for i in range(0, 10):
# Receive samples # Receive samples
# In[55]: # In[35]:
rx_samples = sdr.rx() rx_samples = sdr.rx()
avg_pwr = np.mean(np.abs(rx_samples/coeff)**2) avg_pwr = np.mean(np.abs(rx_samples/coeff)**2)
avg_pwr_dB = round(10*np.log10(avg_pwr), 2) avg_pwr_dB = round(10*np.log10(avg_pwr), 2)
print("check_rx = ", avg_pwr_dB, print("check_rx = ", avg_pwr_dB,
": Best in -30 +/- 5. Else, adjust the rx_hardwaregain") ": Best in -30 +/- 3. Else, adjust the rx_hardwaregain")
# Synchronization and coarse phase correction using the preambule (zeroing AM/PM) # Synchronization and coarse phase correction using the preambule (zeroing AM/PM)
# In[56]: # In[36]:
# Synchronization using cross-corelation # Synchronization using cross-corelation
[paIn, paOut] = corelation(samples, rx_samples, osf) [paIn, paOut] = corelation(samples, rx_samples, osf)
# In[57]: # In[37]:
# Coarse phase correction using the preambule (zeroing AM/PM) # Coarse phase correction using the preambule (zeroing AM/PM)
...@@ -211,7 +230,7 @@ paOut /= np.max(np.abs(paOut)) # scaling ...@@ -211,7 +230,7 @@ paOut /= np.max(np.abs(paOut)) # scaling
# Plot freq domain # Plot freq domain
# In[58]: # In[38]:
[pxxWithout, f] = toPlotSpectrum(paOut, sample_rate, win_fft, 20, "all") [pxxWithout, f] = toPlotSpectrum(paOut, sample_rate, win_fft, 20, "all")
...@@ -226,7 +245,7 @@ plt.show() ...@@ -226,7 +245,7 @@ plt.show()
# Plot AM/AM and AM/PM # Plot AM/AM and AM/PM
# In[59]: # In[39]:
amam_ampm_plot(paIn, paOut) amam_ampm_plot(paIn, paOut)
...@@ -242,12 +261,12 @@ plt.show() ...@@ -242,12 +261,12 @@ plt.show()
# $x(n)$ : dpd input (complex envelope) <br /> # $x(n)$ : dpd input (complex envelope) <br />
# $y_{dpd}(n)$ : dpd output (complex envelope) # $y_{dpd}(n)$ : dpd output (complex envelope)
# In[37]: # In[40]:
dpdModel = {'fs': sample_rate} dpdModel = {'fs': sample_rate}
# set the dpd orders and memory depths # set the dpd orders and memory depths
[Ka, La, Kb, Lb, Mb, Kc, Lc, Mc] = [7, 1, 0, 1, 1, 0, 1, 1] [Ka, La, Kb, Lb, Mb, Kc, Lc, Mc] = [6, 2, 2, 2, 1, 0, 1, 1]
dpdModel['parameters'] = {'Ka': Ka, 'La': La, 'Kb': Kb, dpdModel['parameters'] = {'Ka': Ka, 'La': La, 'Kb': Kb,
'Lb': Lb, 'Mb': Mb, 'Kc': Kc, 'Lc': Lc, 'Mc': Mc} 'Lb': Lb, 'Mb': Mb, 'Kc': Kc, 'Lc': Lc, 'Mc': Mc}
...@@ -268,15 +287,16 @@ dpdOutput *= coeff # scaling for ADALM-Pluto ...@@ -268,15 +287,16 @@ dpdOutput *= coeff # scaling for ADALM-Pluto
# ### Transmit DPD signal # ### Transmit DPD signal
# In[38]: # In[41]:
sdr.tx_destroy_buffer() # Stop transmitting for safe sdr.tx_destroy_buffer() # Stop transmitting for safe
sdr.tx_cyclic_buffer = True # Enable cyclic buffers sdr.tx_cyclic_buffer = True # Enable cyclic buffers
sdr.tx(dpdOutput) # start transmitting with DPD sdr.tx(dpdOutput) # start transmitting with DPD
end = time.time() # end of DPD computation
valid = False valid = True
while (valid): while (valid):
valid = input("1 to set txGain || 0 to compute DPD : ") valid = input("1 to set txGain || 0 to compute DPD : ")
valid = bool(int(valid)) valid = bool(int(valid))
...@@ -295,7 +315,7 @@ while (valid): ...@@ -295,7 +315,7 @@ while (valid):
# ### Receive with DPD signal # ### Receive with DPD signal
# In[39]: # In[42]:
rx_samples = sdr.rx() rx_samples = sdr.rx()
...@@ -307,7 +327,7 @@ print("check_rx = ", avg_pwr_dB, ...@@ -307,7 +327,7 @@ print("check_rx = ", avg_pwr_dB,
# Synchronization of input and output # Synchronization of input and output
# In[40]: # In[43]:
[paIn, paLin] = corelation(samples, rx_samples, osf) [paIn, paLin] = corelation(samples, rx_samples, osf)
...@@ -319,15 +339,15 @@ paLin /= np.max(np.abs(paLin)) # scaling ...@@ -319,15 +339,15 @@ paLin /= np.max(np.abs(paLin)) # scaling
# Plot Linearized AM/AM and AM/PM # Plot Linearized AM/AM and AM/PM
# In[41]: # In[44]:
amam_ampm_plot(paIn, paLin) amam_ampm_plot(paIn, paLin)
plt.show() plt.show()
print("nmse after linearization : ", np.round(nmse(paIn, paLin), 2), " dB") # print("nmse after linearization : ", np.round(nmse(paIn, paLin), 2), " dB")
# In[42]: # In[45]:
plt.figure() plt.figure()
...@@ -354,7 +374,7 @@ plt.show() ...@@ -354,7 +374,7 @@ plt.show()
# Compare spectrum with and without DPD # Compare spectrum with and without DPD
# In[43]: # In[46]:
[pxxWith, f] = toPlotSpectrum(paLin, sample_rate, win_fft, 20, "all") [pxxWith, f] = toPlotSpectrum(paLin, sample_rate, win_fft, 20, "all")
...@@ -369,24 +389,17 @@ plt.show() ...@@ -369,24 +389,17 @@ plt.show()
# Stop transmitting # Stop transmitting
# In[44]: # In[47]:
sdr.tx_hardwaregain_chan0 = -73
sdr.tx_destroy_buffer() sdr.tx_destroy_buffer()
# Print the DPD coefficients # Print the DPD coefficients
# In[45]: # In[48]:
end = time.time()
elapsed = end - start elapsed = end - start
print(f'Elapsed time : {elapsed:.2}ms') print(f'Elapsed time : {elapsed:.2}ms')
# In[46]:
for i in dpdModel['coefGMP']:
print(np.round(i, 3))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment