Modulation of the main frequency band¶
This example shows a simple way to perform main frequency band modulation by multiplying a modulated complex signal by a complex sine wave to perform frequency upconversion. It is preferable to model the system in a complex fundamental frequency band. However, there are some circumstances where it is necessary to model the system in the real bandwidth. An example of this is when a neighbouring frequency band signal is processed with nonlinearity and causes interference in the desired frequency band. This example also illustrates the effect of such interference and is presented in two variants:
- In the form of a script;
- In the form of a model.
The algorithm scheme has the following form:
Building a system using a script¶
First step of system building: connect all used system elements and libraries.
Pkg.add(["CSV"])
using FFTW, Plots
import .EngeeComms
gr()
step = EngeeComms.step;
Create a structure that contains all variables related to the parameters of the connected blocks.
mutable struct passband_modulator
# Transmitter
obj_random_integer
obj_QPSK_modulator
obj_raised_cosine_transmit
# Upconverter
obj_sine_upc
obj_prod_upc
obj_re_upc
# Channel
obj_sum
obj_AWGN
#interference
obj_sine_inter
obj_re_inter
obj_const_inter
obj_math_inter
obj_gain_inter
# Receiver
# downconverter
obj_sine_wave_dc
obj_conj_dc
obj_prod_dc
obj_raised_cosine_receive
obj_QPSK_demodulator
# Metrics
obj_int_to_bit
obj_BER
obj_delay
obj_EVM
function passband_modulator()
new(EngeeComms.random_integer(4, 37, 1e-6, 100, "Int"), EngeeComms.QPSK(pi/4), EngeeComms.rcostrans(0.2, 8, 8, 1.0),
EngeeComms.sine_wave(1.0, 2500000.0, 0.0, "Discrete", "Complex", "Trigonometric fcn", 1e-6/8, 800, "Restart at time zero"), EngeeComms.product(2, "Element-wise"), EngeeComms.complex_to_real_imag("Real"),
EngeeComms.Sum("+"), EngeeComms.AWGN(67, "mode", 8.0, 2, 1/(2*8), 1e-6, 1e-4), EngeeComms.sine_wave(1.0 ,8.833333333333334e+05, 0.0, "Discrete", "Complex", "Trigonometric fcn", 1e-6/8, 800, "Restart at time zero"), EngeeComms.complex_to_real_imag("Real"), 3, EngeeComms.math("pow"), EngeeComms.Gain(.25),
EngeeComms.sine_wave(1.0 ,2500000.0, 0.0, "Discrete", "Complex", "Trigonometric fcn", 1e-6/8, 800, "Restart at time zero"), EngeeComms.math("conj"), EngeeComms.product(2, "Element-wise"), EngeeComms.rcosreciev(0.2, 8, 8, 2.0, 8, 0), EngeeComms.deQPSK(pi/4),
EngeeComms.IntToBit(2, "Unsigned", "MSB first", "Boolean"), EngeeComms.error_rate(16, 0, "Entire frame", "Port", false, false), EngeeComms.delay(8,1), EngeeComms.EVM("Average reference signal power", "Input port", "Input length", 1))
end
end
Create a function to execute the logic of the system operation.
function step1(obj::passband_modulator)
out_upconv1 =[];
out_downcov =[];
out_rec_filt =[];
out_interfer =[];
out_BER =zeros(3);
EngeeComms.setup(obj.obj_random_integer);
EngeeComms.setup(obj.obj_AWGN, [1]);
EVM_out = 0;
for i =1:201
# Передатчик
ri = step(obj.obj_random_integer);
QPSK_tr = step(obj.obj_QPSK_modulator, ri);
raised_cos_tr = step(obj.obj_raised_cosine_transmit, QPSK_tr)
test_rcos = raised_cos_tr;
# Повышающий преобразователь
sine_wave_upc = step(obj.obj_sine_upc);
prod_upc = step(obj.obj_prod_upc, sine_wave_upc,raised_cos_tr);
out_upconv = step(obj.obj_re_upc, prod_upc);
# Канал
# Интерференция с нелинейными искажениями
sine_wave_nonl = step(obj.obj_sine_inter);
re_nonl = step(obj.obj_re_inter, sine_wave_nonl);
inter_pow = step(obj.obj_math_inter, re_nonl, obj.obj_const_inter);
inter_gain = step(obj.obj_gain_inter, inter_pow);
AWGN_in = step(obj.obj_sum, out_upconv, inter_gain);
Channel_out = step(obj.obj_AWGN, AWGN_in);
# Приемник
# Понижающий преобразователь
sine_dc = step(obj.obj_sine_wave_dc);
conj_dc = step(obj.obj_conj_dc, sine_dc);
out_dc = step(obj.obj_prod_dc, conj_dc, Channel_out);
raised_cos_reciev = step(obj.obj_raised_cosine_receive, out_dc[:,1]);
out_reciever = step(obj.obj_QPSK_demodulator, raised_cos_reciev);
# Расчет побитовой ошибки (BER)
out_bits = step(obj.obj_int_to_bit, out_reciever);
rand_int_bits = step(obj.obj_int_to_bit, ri);
BER = step(obj.obj_BER, rand_int_bits, out_bits);
# Расчет EVM_rms
ref_sig = step(obj.obj_delay, QPSK_tr)
EVM_out = step(obj.obj_EVM, ref_sig, raised_cos_reciev)
# Выходы
out_BER = BER;
out_upconv1 = vcat(out_upconv1, out_upconv);
out_downcov = vcat(out_downcov, out_dc);
out_rec_filt = vcat(out_rec_filt, raised_cos_reciev);
out_interfer = vcat(out_interfer, inter_gain);
end
return out_BER, out_upconv1, out_downcov, out_rec_filt, out_interfer, EVM_out;
end
Start the system and get the output data.
passband = passband_modulator() # Вызов структуры
BER,Upconverter,Downconverter,receive_filter,Interference, EVM_out = step1(passband); # Вызов функции
println(BER[1]," BER;") # Вывод данных в командной строке
println(BER[2], " Bit errors;")
println(BER[3], " Bits;")
println()
println(EVM_out, " EVM_rms.") # Построение графика
Plot the spectrum of the signal at the transmitter output and the spectrum of the insertion distortion.
b = Float64.(Upconverter);
spec_b = fftshift(fft(b))[80400:160800];
plot([0:4e6/80400:4e6...],(20log10.(abs.((spec_b)./[4e6/80400,4e6/80400:4e6/80400:4e6...]))), label ="Сигнал на выходе передатчика")
e = Float64.(Interference);
spec_e = fftshift(fft(e))[80400:160800];
plot!([0:4e6/80400:4e6...],20log10.(abs.((spec_e))), label ="Искажения")
ylabel!("Мощность дБВт")
xlabel!("Частота Гц")
plot!(legend=:outerbottom)
ylims!(-240, -60)
xlims!(0.2e6,4e6)
Spectrum of the signal after passing the step-down converter.
d = ComplexF64.(Downconverter);
spec_d = fftshift(fft(d));
plot([-4e6:8e6/160800:4e6-1...],10log10.(abs.((spec_d/3e6))), label ="Сигнал на выходе понижающего преобразователя")
ylabel!("Мощность дБВт")
xlabel!("Частота МГц")
plot!(legend=:outerbottom)
Scheme of the signal constellation.
f = ComplexF64.(receive_filter);
plot(f[end-200:end], seriestype=:scatter)
plot!([0.75+0.75im, 0.75-0.75im, -0.75+0.75im, -0.75-0.75im], seriestype=:scatter, lc=:red, lw=:5, ls =:dot)
plot!(legend=:none)
xlabel!("Синхфазная амплитуда")
ylabel!("Квадратурная амплитуда")
Model building¶
Now let's consider the second way of building communication systems, which is modelling digital signal processing using Engee models.
*Passbanmod
Interference with Nonlinearity
Upconverter
Downconverter
Calculate RMS EVM
*♪ Compute BER ♪
function run_model( name_model, path_to_folder )
Path = path_to_folder * "/" * name_model * ".engee"
if name_model in [m.name for m in engee.get_all_models()] # Проверка условия загрузки модели в ядро
model = engee.open( name_model ) # Открыть модель
model_output = engee.run( model, verbose=true ); # Запустить модель
else
model = engee.load( Path, force=true ) # Загрузить модель
model_output = engee.run( model, verbose=true ); # Запустить модель
engee.close( name_model, force=true ); # Закрыть модель
end
return model_output
end
# Запуск модели
run_model( "passbandmod", @__DIR__ )
# Подключение библиотек
using CSV, DataFrames
using Plots # Подключение библиотеки для построения графиков
gr() # Подключение бэкенда - метода отображения графики
## EVM
EVM = Matrix(CSV.read("$(@__DIR__)/EVM.csv", DataFrame)); #загрузка данных
plot(EVM[:,1], EVM[:,2], xlabel="Время", ylabel="EVM", title="EVM") # Построение графика
## BER
BER = Matrix(CSV.read("$(@__DIR__)/BER.csv", DataFrame)); #загрузка данных
plot(BER[:,1], BER[:,2], xlabel="Время", ylabel="BER", title="BER") # Построение графика
Conclusion¶
We have implemented a script and model of a simple way to perform basic bandwidth modulation by multiplying a modulated complex signal by a complex sine wave to perform frequency upconversion. And also showed how to use scripts and models for digital signal processing in Engee.