RF Impairments & Corrections
Est. read time: 1 minute | Last updated: May 04, 2026 by John Gentile
Contents
from IPython.display import YouTubeVideo, Markdown
import inspect
import numpy as np
import matplotlib.pyplot as plt
import scipy
from rfproto import impairments
YouTubeVideo('PNMOwhEHE6w')
YouTubeVideo('LBLvmNyAdSI')
Noise
Thermal Noise
Defined by the equation:
Where:
- is the Boltzmann Constant
- is the device temperature in Kelvin
- is the receiver bandwidth in Hertz
- is the noise factor of the system
Markdown(f"```python\n{inspect.getsource(impairments.thermal_noise)}\n```")
def thermal_noise(T, B, Fn):
return scipy.constants.k * T * B * Fn
At room temp (290 Kelvin), this relates to a noise power spectral density of -144 dBW/MHz, which means for every 1 MHz of bandwidth, -144 dBW of thermal noise is added).
room_temp = 290
bw = 10e6
# convert to dBW, then +30 to dBmW
therm_noise = 10*np.log10(impairments.thermal_noise(room_temp, bw, 1)) + 30
print(f"Thermal noise at room temp, {bw/1e6}MHz bandwidth: {therm_noise:.4} dBmW")
Thermal noise at room temp, 10.0MHz bandwidth: -104.0 dBmW
DC Offset Removal
I/Q Offset Correction
Wireless Channels
N = 5000000
EbNodB_range = range(11)
itr = len(EbNodB_range)
ber = [None]*itr
for n in range (itr):
EbNodB = EbNodB_range[n]
EbNo=10.0**(EbNodB/10.0)
x = 2 * (np.random.rand(N) >= 0.5) - 1
noise_std = 1/np.sqrt(2*EbNo)
y = x + noise_std * np.random.randn(N)
y_d = 2 * (y >= 0) - 1
errors = (x != y_d).sum()
ber[n] = 1.0 * errors / N
plt.figure()
plt.plot(EbNodB_range, ber, 'bo', EbNodB_range, ber, 'k')
plt.axis([0, 10, 1e-6, 0.1])
plt.xscale('linear')
plt.yscale('log')
plt.xlabel('EbNo(dB)')
plt.ylabel('BER')
plt.grid(True)
plt.title('BPSK Modulation')
plt.show()

References
- Direct Conversion (Zero-IF) Receiver - Wireless Pi
- Digitally Removing a DC Offset: DSP Without Mathematics
- What does correcting I/Q do? - DSP Stack Exchange