Engee documentation
Notebook

DMR protocol physical layer system model

Modern digital radio communication systems require high reliability and efficiency of data transmission, especially if there are risks of data distortion and mis-synchronisation. One of the key protocols used in professional mobile radio communications is DMR (Digital Mobile Radio), which provides digital voice and data transmission using efficient modulation and coding techniques.

This project considers a system model of the DMR protocol, including the complete signal processing chain, from packet generation to demodulation and synchronisation at the receiving end. Modelling of each stage of signal transmission allows to analyse the robustness of the system to various types of interference and distortion.

The DMR protocol, like many other telecommunications standards, uses a layered architecture similar to the OSI (Open Systems Interconnection) model. The main DMR layers can be divided as follows.

  1. Physical Layer (PHY). Responsible for the transmission and reception of bit streams over the radio channel and includes modulation (4-FSK, FM), filtering, synchronisation and distortion correction in the channel (the physical layer also includes coding, but it is not considered in this example).

  2. Data Link Layer (DLL). Provides reliable data transmission between nodes, manages access to the medium. Includes the generation of DMR packets, such as voice, signalling data. This example demonstrates data packets. It may also include error control (CRC, FEC), logical channel management (TDMA, two slots), addressing (subscriber and group identification).

  3. Network Layer (Network Layer). Provides routing and inter-network communication if the DMR is integrated into a larger system that includes the Internet.

  4. In some implementations there are additional layers: Transport Layer (if DMR works over IP) or, for example, Application Layer - support of services (voice, text messages, telemetry).

In the DMR standard, the focus is on the physical and data link layers, as these define the operation of the radio channel. Network functions are more often realised in infrastructure solutions (e.g. repeaters and control systems).

Connecting an auxiliary model start function

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)

Running the model and analysing the results

The model we have implemented includes the following key blocks.

  1. Packet Generation - generation of signalling sequence and empty blocks corresponding to DMR packet types.

  2. 4-FSK modulation - digital modulation used in DMR for efficient bandwidth utilisation.

  3. Elevated Cosine Filter - used to limit the signal spectrum and minimise inter-symbol interference.

  4. FM Modulator - converts a digital signal to analogue form for transmission over a radio channel.

  5. Sync Simulation Link - simulates the time mismatch between transmitter and receiver. image_3.png

  6. Detection of signal sequence and frame synchronisation - algorithms for restoring the temporal position of packets at the receiving end.
    image_5.png

To test the correct transmission of messages in Russian and English we will use pangrams in these two languages.

A pangram (from Greek - "all letters"), or multibook, is a short text that uses all or almost all letters of the alphabet without repeating them, if possible.

Let's specify such a message, and in the model we will represent it in byte form for convenience of interaction with the signal and supplement the message with zeros to the number of elements in the vector, a multiple of 27 (216 bits of data in one DMR packet). Some of the code from the model is presented below.

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

The screenshot below shows the implemented model in its entirety.

image.png

Let's run our model at SNR = 25 in order to see the result with the lowest number of errors. If you are interested in the noise immunity of the system, you can experiment with this parameter yourself.

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")

)

Let's analyse the results. First, let's display the byte representation of the input and output text message, as well as the number of errors by byte.

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]:

As we see, at SNR = 25 no errors are observed, and, therefore, we can decode the text message without errors.

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ъешь же ещё этих мягких французских булок, да выпей чаю.

Conclusion

In this example the DMR system model has been analysed, affecting only the physical layer of the protocol. In the future, if the topic is of interest to the community, we will look at other layers of the protocol and present the implementation of its various components.

Blocks used in example