I am trying to generate IQ components for 2FSK modulation. I have started off from this thread FSK and IQ modulation , but I don't quite understand the IQ TX components plotted in the example there by GordonFreeman.

In my view, in a 2FSK modulation, the angle of I+jQ shall vary linearly with time (constant frequency +/- Δf), drawing a circle either counter-clockwise with frequency Δf if TX data is equal to 1, or clockwise with frequency Δf if the TX data is equal to -1 (given e.g. a random -1/+1 sequence). In this convention, the difference between high and low freqs in 2FSK is 2*Δf.

This is well explained from about 07:00 in the following video: https://www.youtube.com/watch?v=5GGD99Qi1PA (can be played at faster speed if convenient).

If I understand correctly, for 2FSK modulation:



with e.g. freq(k)=Δf*k where transmitted symbol k=-1/+1 if we have a binary data stream of +1/-1. In this sense, I(k) will be just a cosine wave, while Q(k) will be a sine wave which will be pi shifted every time there is a data change. An example are below IQ components I generated by a pyscript: enter image description here

The above components are generated when bitrate is maximum(4*Δf).

Does this make sense?


Thanks for your comments Dan.

Some more info- I started off from a 2FSK modulated signal of this form:


where fcarr is the carrier frequency, freq(k) is either +Δf or -Δf as discussed depending of the transmitted data.

Then deriving the below I/Q components (those that fed into a quadrature modulator would lead to the above modulated signal, I omit the full derivation but that can be derived either in freq domain https://en.wikipedia.org/wiki/Single-sideband_modulation or more simply in time domain with trigo formulas https://en.wikipedia.org/wiki/Quadrature_modulation):



Therefore when freq(k) is changing from +Δf to -Δf, the I(k) which is a cosine will remain unchanged (if we multiply by -1 the arg of a cosine, the cosine won't change), while Q(k) which is a sine will change of a 180 degrees since sin(-x)=-sin(x). In this sense, the rotation of the I/Q vector will be changing from counter clockwise to clockwise, but there will be a sudden phase shift of 180 degrees.

If maximum bitrate = 4*Δf is choosen, then duration of 1 symbol is 1/fourth of Δf period, or 90 degrees in the I/Q vector diagram.

So I/Q vector will start from (1,0) i.e. 0 degrees, moving counterclock wise to (0,1) i.e. 90 degrees, that will be within the duration of symbol "1" , then there will be a symbol change to "-1", that will produce, as mentioned above, just a change of I component from sin(2*piΔft) to -sin(2*piΔft). This will make the I/Q vector moving from (0,1) to (0,-1) and the vector will move now clockwise to (-1,0) for the duration of symbol "-1".

From this, the above I/Q plot was generated.

  • $\begingroup$ No your final plot does not make sense to me but I am trying to follow how you came to that conclusion since the rest of your description gives me the impression that your understanding of the signalling is solid. I may be missing something or can figure out your misunderstanding if you explain further how you got that plot. I follow the trajectory on and IQ plane and see that you have a carrier that is always magnitude = 1, that starts at angle 0°, and rotates counter clockwise (positive F) to 90° but then abruptly changes 180° to be at -90° (why??). I didn't continue past that... $\endgroup$ Nov 30, 2018 at 18:30
  • $\begingroup$ But if this was simple FSK (not GMSK, etc) then I would expect with the data transition the trajectory to rotate from that point at +90° clockwise for the duration of the next symbol. That is not what is happening here, yet your earlier description makes it sound like you understand that- so what am I missing? $\endgroup$ Nov 30, 2018 at 18:31
  • $\begingroup$ (My reference to GMSK etc is simply that here with simple FSK the changes in phase will be abrupt while in those other FSK variants we smooth the changes to reduce spectral occupancy, yet in all cases the phase trajectory as given by our location on the unit circle will be continuous) $\endgroup$ Nov 30, 2018 at 18:33

1 Answer 1


Your I & Q plots look wrong to me. Instead of trying to sort out what you may have done wrong, let me just give you a working example instead.

The following GNU Octave (Matlab clone) script shows how to generate the I & Q of 2-FSK with square pulses and a modulation index of $1/2$ (which should correspond to a bit rate of $4\cdot\Delta f$).

The "magic" happens on the lines following the comment "Frequency modulate the baseband packet"

% Keep Octave happy
pkg load signal;

% Bit rate
Rb = 9600;

% Modulation index; 1/2 is Minimum Shift Keying.
modulation_index = 1/2;

% Optional frequency shift for demonstration of modulation on a
% carrier within -Fs/2 to +Fs/2
freq_shift_hz = 0;

% Samples per symbol and sample rate out of the modulation process
sps = 10;
Fs = Rb * sps;

% pulse filter taps - square pulses 
taps_pf = ones(sps, 1)/sps;

% Create a random bit string
nbits = 16;
message_bits = round(rand(nbits,1));
nrz_message_bits = (message_bits - 0.5)*2;

% Upsample and pulse shape the packet
% N.B. Octave's filter function sets up a history of 0's for us.
x = sps*[upsample(nrz_message_bits, sps); zeros(1, 1)];
packet_baseband = filter(taps_pf, [1], x);

% Throw in a frequency shift (as a level shift of the unscaled baseband)
% for demonstration purposes
freq_shift = freq_shift_hz / (Rb/2 * modulation_index);
packet_baseband = packet_baseband + freq_shift;

% Frequency modulate the baseband packet
fm_gain = pi/(Fs/2) * Rb/2 * modulation_index;
x = packet_baseband * fm_gain;
phase = cumsum(x); % phase is integral of frequency
packet_modulated = exp(1i*mod(phase, 2*pi));

title('Message Bits');
xlabel('Bit number');
grid on;

N1 = length(packet_baseband);
t1 = [0:N1-1]/Fs;
plot(t1, packet_baseband * Rb/2 * modulation_index, 'x-');
title('Upsampled, Pulse Shaped, Scaled, and Level Shifted NRZ Bits');
xlabel('Time (seconds)');
ylabel('Frequency Deviation (Hz)');
grid on;

N2 = length(phase);
t2 = [0:N2-1]/Fs;
plot(t2, phase, '.-');
title('Accumulated Phase');
xlabel('Time (seconds)');
ylabel('Accumulated Phase (radians)');
grid on;

N = length(packet_modulated);
t = [0:N-1]/Fs;
plot(t, real(packet_modulated), t, imag(packet_modulated));
title('I & Q of 2-FSK Modulated Signal');
xlabel('Time (seconds)');
grid on;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.