Engee documentation
Notebook

4-FSK modulator and demodulator

In this example, we will look at working with 4-FSK (Frequency Shift Keying) in Engee. Frequency modulation is a type of modulation in which information is encoded by changing the frequency of a signal. 4-FSK, four–level frequency manipulation, is a type of modulation used in DMR (Digital Mobile Radio), and it is also optimal for use in PMR (Professional Mobile Radio) systems.

Each pair of information bits
defines a frequency shift relative to the carrier frequency.

The envelope in this type of modulation is constant, which provides significant advantages in terms of consumption and construction of the transmitter circuit:
there are no strict requirements to ensure the linearity of the transmission path. The bit encoding is performed based on the table below.

Bit combination The corresponding symbol (4-FSK)
11 3
10 1
00 -3
01 -1

We will build a 4-FSK modulator and demodulator on the basic elements.

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)

The model contains two main units: a modulator and a demodulator. A bit stream is supplied at the input, after which we use a buffer to form packets of two samples and perform modulation and demodulation. In our example, the conditions for the operation of the modulator and demodulator are ideal: there is no communication channel and no interference.

image_2.png

Next, let's run the model and analyze the simulation results.

In [ ]:
run_model("4fsk")
Building...
Progress 0%
Progress 4%
Progress 9%
Progress 14%
Progress 19%
Progress 24%
Progress 29%
Progress 34%
Progress 39%
Progress 44%
Progress 49%
Progress 54%
Progress 59%
Progress 64%
Progress 69%
Progress 74%
Progress 79%
Progress 85%
Progress 90%
Progress 95%
Progress 100%
Progress 100%
Out[0]:
SimulationResult(
    "4-FSK demodulator.Out1" => WorkspaceArray{Vector{Int64}}("4fsk/4-FSK demodulator.Out1")
,
    "Buffer.1" => WorkspaceArray{Vector{Float64}}("4fsk/Buffer.1")
,
    "Add.1" => WorkspaceArray{Float64}("4fsk/Add.1")
,
    "SumError.ErrorCnt" => WorkspaceArray{Float64}("4fsk/SumError.ErrorCnt")

)

Let's compare the input group of bits with the output bits.

In [ ]:
In_bit = collect(simout["4fsk/4-FSK demodulator.Out1"]);
Out_bit = collect(simout["4fsk/Buffer.1"]);
In_and_Out_bit = [In_bit.value Out_bit.value]
Out[0]:
5001×2 Matrix{Vector{Float64}}:
 [0.0, 0.0]  [0.0, 0.0]
 [1.0, 1.0]  [1.0, 1.0]
 [0.0, 1.0]  [0.0, 1.0]
 [1.0, 0.0]  [1.0, 0.0]
 [0.0, 1.0]  [0.0, 1.0]
 [1.0, 1.0]  [1.0, 1.0]
 [0.0, 1.0]  [0.0, 1.0]
 [1.0, 0.0]  [1.0, 0.0]
 [1.0, 0.0]  [1.0, 0.0]
 [0.0, 1.0]  [0.0, 1.0]
 [1.0, 1.0]  [1.0, 1.0]
 [1.0, 0.0]  [1.0, 0.0]
 [1.0, 1.0]  [1.0, 1.0]
 ⋮           
 [0.0, 0.0]  [0.0, 0.0]
 [0.0, 1.0]  [0.0, 1.0]
 [1.0, 0.0]  [1.0, 0.0]
 [0.0, 1.0]  [0.0, 1.0]
 [1.0, 1.0]  [1.0, 1.0]
 [0.0, 0.0]  [0.0, 0.0]
 [1.0, 0.0]  [1.0, 0.0]
 [1.0, 1.0]  [1.0, 1.0]
 [1.0, 0.0]  [1.0, 0.0]
 [1.0, 0.0]  [1.0, 0.0]
 [1.0, 1.0]  [1.0, 1.0]
 [0.0, 0.0]  [0.0, 0.0]

As we can see from the explicit comparison of the bit pairs, all sequences are recognized correctly. Now let's look at the numerical error rate in our model.

In [ ]:
ErrorCnt = collect(simout["4fsk/SumError.ErrorCnt"]);
ErrorCnt = ErrorCnt.value;
print("Кол-во ошибок за всё время моделирования: $(ErrorCnt[end])")
Кол-во ошибок за всё время моделирования: 0.0

Conclusion

The simulation results are as follows: the modulator and demodulator that we have implemented work correctly, without errors. This means that such an implementation can be applied to communication protocols, for example, DMR.