MSK (Minimum Shift Keying) - вид частотной модуляции с минимальным разносом частот. Это более продвинутая версия CPFSK модуляции, которая имеет непрерывную фазу, но у которой индекс модуляции, отвечающий за расстояние между частотами для нуля и единицы, минимален.
Перед переходом к MSK рекомендую ознакомиться с CPFSK и FSK модуляциями. Ссылки на эти модуляции можно найти на главной странице моего сайта. Главным отличием MSK от CPFSK является ширина спектра. В MSK он минимален, что позволяет использовать все плюсы CPFSK и занимать еще меньше полосы пропускания. Разберемся немного лучше на что влияет индекс модуляции и где найти его в формулах. При обычной CPFSK модуляции мы выбираем базовую частоту и уже на ее основе определяем две другие частоты, одну для нуля, вторую для единицы.
В приведенных формулах Tb - это длительность одного бита, а fsk_index и есть тот индекс, которым отличается CPFSK от MSK. Этот индекс напрямую влияет на разнос частот. Как видно из формул - чем больше индекс, тем больше разнос частот. Стандартные значения этого индекса: 1, 2, 3, 5. Посмотрим как меняется разнос частот в CPFSK при изменении этого индекса. Длительность одного бита будет равна 1 секунде.
xxxxxxxxxx431Fs = 1000;2Tb = 1;3t = 0:1/Fs:Tb-1/Fs;4
5fsk_indices = [0.1, 0.5, 1, 3, 5];6w_base = 50;7figure;8
9for idx = 1:length(fsk_indices)10 fsk_index = fsk_indices(idx);11 w_deviation = pi * (1/Tb) * fsk_index;12
13 w0 = w_base - w_deviation;14 w1 = w_base + w_deviation;15
16 bits = [0 1 0 0 1 0 0 0 0 1 1 0 0 1];17
18 phase = 0;19 CPFSK_signal = [];20 for i = 1:length(bits)21 if bits(i) == 022 freq = w0;23 else24 freq = w1;25 end26 for j = 1:length(t)27 phase = phase + freq / Fs;28 CPFSK_signal = [CPFSK_signal cos(phase)];29 end30 end31
32 N = length(CPFSK_signal);33 f = (-N/2:N/2-1)*(Fs/N);34 Y_CPFSK = fftshift(fft(CPFSK_signal, N));35 P_CPFSK = abs(Y_CPFSK/N);36
37 subplot(length(fsk_indices), 1, idx);38 plot(f, P_CPFSK);39 title(['Spectrum of CPFSK Modulated Signal (fsk\_index = ', num2str(fsk_index), ')']);40 xlabel('Frequency (Hz)');41 ylabel('|P(f)|');42 xlim([-20 20]);43endПри запускаем получим 5 спектров сигналов с разными fsk_index: 0.1, 0.5, 1, 3, 5.

На графике четко видно разницу между частотами при индексе 5, но при уменьшении индекса модуляции разница становится всё меньше. В какой-то момент, а именно при 0.5, различить на спектре частоты становится очень сложно, а при 0.1 вообще невозможно, потому что они сливаются в одну.
Чтобы найти нужный индекс модуляции нужно решить задачу с ортогональностью несущих частот в сигнале. Ортогональность - это свойство двух функций или векторов, которые взаимно перпендикулярны в простанстве состояний, что в контексте сигналов означает, что их перекрестное влияние друг на друга минимально или вообще отсутствует. То есть задача ортогональности сводится к тому, чтобы найти такие частоты с минимальным разносом, которые бы не влияли друг на друга и смогли бы быть восстановлены при приеме и демодуляции сигнала.
Для двух функций f1(t) и f2(t), которые определены на интервале [a,b], они ортогональные если их скалярное произведение равно нулю. Математически это выглядит следующим образом.
Если проецировать это на сигналы, то ортогональные несущие это сигналы, чьи частоты или фазы выбраны таким образом, чтобы они были ортогональны друг другу.
Рассмотрим пример с двумя сигналами с разными частотами.
Эти сигналы будут ортогональными, если их скалярное произведение будет равно нулю. Подставим их в формулу с интегралом.
Для гармонических функций с различными частотами это условие выполняется, если Т - период наименьшего общего кратного периодов двух сигналов. Интегрируя выражение получаем следующее. Заменим частоты на угловые и решим интеграл.
Используя тригонометрическое тождество произведения косинусов и подставляем его в интеграл. Теперь можем разбить один большой интеграл на два.
Теперь проанализируем два интеграла отдельно. Первый интеграл.
Интеграл косинуса будет равен нулю, если его аргумент будет равен 2pi умноженному на любое целое число. Используя это свойство получаем.
Второй интеграл.
Следуя прошлому правилу получаем.
В обоих случаях k и m - это константы отличные от нуля.
Вернемся к MSK. В MSK частоты f1 и f2 выбираются таким образом, чтобы сигналы были ортогональный. Частоты для 1 и 0 соответственно равны.
Где f_base - центральная частота, а delta f - девиация частоты. Tb - длительность 1 бита. Тогда, для ортогональности частот f0 и f1.
Так как k - это целое число не равное нулю, то его минимальное значение будет 1. Именно по этой формуле рассчитывается девиация частот для MSK, FSK и CPFSK. Она позволяет получить минимальную разницу между частотами и добиться наименьшей ширины спектра. Индекс модуляции для MSK можно получить используя формулу индекса модуляции через скорость передачи и девиацию частоты.
Соответственно индекс модуляции для MSK всегда равен 0.5. Именно за счет ортогональности сигналов и низкого индекса модуляции мы получаем узкий спектр, что дает множество преимуществ MSK перед CPFSK.
Изучим спектральную разницу между CPFSK с индексом модуляции 1 и MSK. Для этого используем следующим код.
xxxxxxxxxx691Fs = 1000;2Tb = 1;3t = 0:1/Fs:Tb-1/Fs;4
5w_base = 50;6
7fsk_index_cpfsk = 1;8w_deviation_cpfsk = pi * (1/Tb) * fsk_index_cpfsk;9
10w0_cpfsk = w_base - w_deviation_cpfsk;11w1_cpfsk = w_base + w_deviation_cpfsk;12
13bits = [0 1 0 0 1 0 0 0 0 1 1 0 0 1];14
15phase = 0;16CPFSK_signal = [];17for i = 1:length(bits)18 if bits(i) == 019 freq = w0_cpfsk;20 else21 freq = w1_cpfsk;22 end23 for j = 1:length(t)24 phase = phase + freq / Fs;25 CPFSK_signal = [CPFSK_signal cos(phase)];26 end27end28
29N = length(CPFSK_signal);30f = (-N/2:N/2-1)*(Fs/N);31Y_CPFSK = fftshift(fft(CPFSK_signal, N));32P_CPFSK = abs(Y_CPFSK/N);33
34fsk_index_msk = 0.5;35w_deviation_msk = pi * (1/Tb) * fsk_index_msk;36
37w0_msk = w_base - w_deviation_msk;38w1_msk = w_base + w_deviation_msk;39
40phase = 0;41MSK_signal = [];42for i = 1:length(bits)43 if bits(i) == 044 freq = w0_msk;45 else46 freq = w1_msk;47 end48 for j = 1:length(t)49 phase = phase + freq / Fs;50 MSK_signal = [MSK_signal cos(phase)];51 end52end53
54N = length(MSK_signal);55f = (-N/2:N/2-1)*(Fs/N);56Y_MSK = fftshift(fft(MSK_signal, N));57P_MSK = abs(Y_MSK/N);58
59figure;60plot(f, P_CPFSK, 'r', 'DisplayName', 'CPFSK (fsk\_index = 1)');61hold on;62plot(f, P_MSK, 'b', 'DisplayName', 'MSK (fsk\_index = 0.5)');63title('Spectr of CPFSK and MSK Modulated Signals');64xlabel('Frequency (Hz)');65ylabel('|P(f)|');66xlim([-20 20]);67legend('show');68hold off;69
При запуске получаем следующие графики.

Как видно спектр MSK немного уже спектра CPFSK. Это позволяет более эффективно использовать полосы частот, снизить межканальные помехи и улучшить устойчивость к шуму.
https://ru.dsplib.org/content/signal_msk/signal_msk.html#:~:text=MSK%20%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F%20%D1%8D%D1%82%D0%BE%20%D1%87%D0%B0%D1%81%D1%82%D0%BD%D1%8B%D0%B9%20%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9,%D0%B8%20%C2%AB1%C2%BB%20(%D1%82. https://digteh.ru/UGFSvSPS/modul/MSK/