Engee 文档
Notebook

DMR 协议物理层系统模型

现代数字无线电通信系统要求数据传输具有高可靠性和高效率,尤其是在存在数据失真和误同步风险的情况下。专业移动无线电通信中使用的主要协议之一是DMR(数字移动无线电),它利用高效的调制和编码技术提供数字语音和数据传输。

本项目考虑了**DMR 协议的系统模型,包括从数据包生成到接收端解调和同步的完整信号处理链。对信号传输的每个阶段进行建模,可以分析系统对各种干扰和失真的稳健性。

DMR 协议与许多其他电信标准一样,采用类似于 OSI(开放系统互连)模型的分层结构。DMR 的主要层级可划分如下。

1.物理层(PHY)。负责通过无线电信道传输和接收比特流,包括信道中的调制(4-FSK、FM)、滤波、同步和失真校正(物理层还包括编码,但在本例中不考虑)。

2.数据链路层(DLL)。提供节点间可靠的数据传输,管理对介质的访问。包括生成 DMR 数据包,如语音、信号数据。本例演示数据包。它还可能包括错误控制(CRC、FEC)、逻辑信道管理(TDMA、双时隙)、寻址(用户和组识别)。 3.网络层(Network Layer)。如果 DMR 集成到包括互联网在内的更大系统中,则提供路由选择和联网功能。 4.4. 在某些实施方案中还有附加层:传输层(如果 DMR 通过 IP 工作)或应用层--支持服务(语音、文本信息、遥测)。

在 DMR 标准中,重点是物理层和数据链路层,因为这些层定义了无线电信道的运行。网络功能通常在基础设施解决方案(如中继器和控制系统)中实现。

连接辅助模型启动功能

In [ ]:
function run_model( name_model)
    
    Path = (@__DIR__) * "/" * 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
    sleep(5)
    return model_output
end
Out[0]:
run_model (generic function with 1 method)

运行模型并分析结果

我们实施的模型包括以下关键模块。
1.数据包生成 - 生成与 DMR 数据包类型相对应的信令序列和空块。 2.4-FSK 调制 - DMR 中使用的数字调制,可有效利用带宽。 3.提升余弦滤波器 - 用于限制信号频谱和尽量减少符号间干扰。
4.调频调制器 - 将数字信号转换为模拟信号,通过无线电信道传输。
5.同步模拟链路 - 模拟发射机和接收机之间的时间错配。 image_3.png

6.信号序列检测和帧同步 - 在接收端恢复数据包时间位置的算法。
image_5.png

为了测试俄语和英语信息传输的正确性,我们将使用这两种语言的泛函。

pangram(源于希腊语--"所有字母"),或 multibook,是指尽可能不重复地使用所有或几乎所有字母的短文。

让我们来定义这样的信息,在模型中,为了方便与信号交互,我们将以字节形式表示信息,并用零补充信息,使其达到矢量中元素的数量,即 27 的倍数(一个 DMR 数据包中包含 216 比特数据)。下面是模型中的部分代码。

In [ ]:
En = "Red fox jumps over the lazy dog"
Ru = "Cъешь же ещё этих мягких французских булок, да выпей чаю"
inp_sms = "$En. $Ru."
println("Входное сообщение:")
println(inp_sms)
println()
bytes = Int.(Vector{UInt8}(inp_sms))
remainder = length(bytes) % 27
bytes = vcat(bytes, remainder == 0 ? Int[] : zeros(Int, 27 - remainder))
println("Байтовое представление:")
println(bytes)
println()
println("Количество кадров для сообщения: $(length(bytes)/27)")
Входное сообщение:
Red fox jumps over the lazy dog. Cъешь же ещё этих мягких французских булок, да выпей чаю.

Байтовое представление:
[82, 101, 100, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103, 46, 32, 67, 209, 138, 208, 181, 209, 136, 209, 140, 32, 208, 182, 208, 181, 32, 208, 181, 209, 137, 209, 145, 32, 209, 141, 209, 130, 208, 184, 209, 133, 32, 208, 188, 209, 143, 208, 179, 208, 186, 208, 184, 209, 133, 32, 209, 132, 209, 128, 208, 176, 208, 189, 209, 134, 209, 131, 208, 183, 209, 129, 208, 186, 208, 184, 209, 133, 32, 208, 177, 209, 131, 208, 187, 208, 190, 208, 186, 44, 32, 208, 180, 208, 176, 32, 208, 178, 209, 139, 208, 191, 208, 181, 208, 185, 32, 209, 135, 208, 176, 209, 142, 46]

Количество кадров для сообщения: 5.0

下面的截图显示了整个模型的执行情况。

image.png

让我们在 SNR = 25 的条件下运行模型,看看误差最小的结果。如果您对系统的抗噪能力感兴趣,可以自行实验该参数。

In [ ]:
snr = 25
run_model("DMR") # Запуск модели.
Out[0]:
SimulationResult(
    "err_symbol" => WorkspaceArray{Vector{Int64}}("DMR/err_symbol")
,
    "Frame_Synchronization.Delay" => WorkspaceArray{Float64}("DMR/Frame_Synchronization.Delay")
,
    "Inp" => WorkspaceArray{Vector{Int64}}("DMR/Inp")
,
    "Out" => WorkspaceArray{Vector{UInt32}}("DMR/Out")

)

让我们来分析一下结果。首先,我们来显示输入和输出文本信息的字节表示法,以及按字节分列的错误数。

In [ ]:
println("SNR: $snr")
error_bytes = reduce(vcat,collect(simout["DMR/err_symbol"]).value)
println("Кол-во ошибок: $(sum(error_bytes.>0))")
Delay = reduce(vcat,collect(simout["DMR/Frame_Synchronization.Delay"]).value)
println("Битовая задержка: $(Int.(Delay[end]))")

Input = reduce(vcat,collect(simout["DMR/Inp"]).value)
plot(Input, seriestype = :steppre,  label = "Input")
Output = reduce(vcat,collect(simout["DMR/Out"]).value)
plot!(Output, seriestype = :steppre,  label = "Output")
SNR: 25
Кол-во ошибок: 0
Битовая задержка: 20
Out[0]:

正如我们所看到的,在 SNR = 25 时,没有发现任何错误,因此我们可以无误地解码文本信息。

In [ ]:
SMS_sim = reduce(vcat, collect(SMS_out).value)
SMS = filter(x -> x != 0x00000000, SMS_sim)
SMS = String(UInt8.(SMS))
println("Восстановленная строка: ", SMS)  # Лишние нули игнорируются
Восстановленная строка: Red fox jumps over the lazy dog. Cъешь же ещё этих мягких французских булок, да выпей чаю.

结论

本示例分析了 DMR 系统模型,仅涉及协议的物理层。今后,如果社区对这一主题感兴趣,我们将研究协议的其他层,并介绍其各组成部分的实现情况。