image thumbnail

A Few Modulations

by

 

ASK, BPSK, FSK and QPSK modulations done by hand.

fsk_mod

Contents

function modulated = fsk_mod( msg, varargin )

A function to perform Frequency Shift Keying

     Using good form and properly vectorized code, we generate the FSK
     sequence of the msg passed from user land.  Plots are generated to
     show the result generated from the original bits.
     modulated = FSK_MOD( msg )  "msg" can be a row vector if you only want to modulate one
     message, or you can create a matrix... with the rows comprising the messages.  The
     result will be either a vector or a matrix of modulated signal.
     modulated = FSK_MOD( msg, samples_per_symbol ) The user can set the number of samples
     per symbol in the final modulated carrier.
     modulated = FSK_MOD( msg, samples_per_symbol, do_plot ) If the user wants to turn off
     the plotting, just set the third argument to anything.
     Example :
     >> msg = [1 0 0 0 1 1 1 0 1];
     >> fsk_mod( msg );
     ** Poof... magic plots **
     Example #2 :
     >> msg = [[1 0 0 0 1 1 1 0 1]; [0 1 0 0 1 0 1 0 1]];
     >> fsk_mod( msg );
     ** Poof... more magic plots **

SEE ALSO : ASK_MOD, BPSK_MOD, QPSK_MOD

    narginchk( 1, 3 );

    % Some input checking : Only allow 0's and 1's.
    if ~isempty(find( msg ~= 0 & msg ~= 1, 1 ))
        error( 'Only values between 0 and 1 are supported for modulation in ASK.' );
    end

    % Check the shape of what the user gave us.  I decided to make this work on matrices of
    % bits.  So each row will be a message.
    [m,n] = size(msg);

    % We're going to oversample a bit so we can see good resolution on the
    % sine wave we will be generating for the carrier wave.
    samples_per_symbol = 100;
    if nargin >= 2
        % Allow the user to override the samples per symbol
        samples_per_symbol = varargin{1};
    end

    % Let the user turn off verbose prints/plots
    doplot = 1;
    if nargin >= 3
        doplot = 0;
    end
Error using fsk_mod (line 29)
Not enough input arguments.

Variable Declarations

    % Hz : Frequency of the carrier signal.  To be precise, the actual
    % frequency is f/samples_per_bit.  So 2Hz.
    f = 200;

    % Generate our time vector for the sine wave generation.  We're
    % creating one period, so from 0->2*pi in steps of
    % 2*pi/samples_per_bit.  i.e. 0->2*pi in 100 steps, evenly divided.
    t=0:2*pi/(samples_per_symbol-1):2*pi;

    modulated = zeros( m, samples_per_symbol*n );

The actual work is done in the following 6 lines

This is a little bit of MATLAB magic. 'repmat' stands for replicate matrix. So, now 't' consists of cycles of 0->2*pi. There are as many cycles from 0->2*pi as we have bits in the original msg.

Alternatively, you could do this the n00b way and make a for loop like this...

temp( = []; % Make a matrix with scope outside the for loop. for n = 1:length(msg) temp = [temp t]; <---- This is matrix concatenation... end t = temp;

But one piece of advice : You should avoid for loops like the plague in MATLAB. There is always a "vectorized" way to accomplish the same task in MATLAB, and for loops are slow in m-code, while vectorization is blazing fast. Also, the for loop grows an array dynamically which also incurs memory penalties and is slow and not good practice. In fact, MATLAB's lint tool has now started warning about that. n00bish. But repmat is pro.

    t = repmat( t, 1, n );

    % Now we need to oversample our msg.  This is for convenience in the
    % multiply later.  i.e. we want our 10011101 to look like...
    % 1111111 0000000 000000 1111111 11... etc.  We want as many
    % replications of the bits as we're oversampling... so samples_per_bit.
    % However, we've replicated the vector as follows...
    % 1 0 0 1 1 1 0 1
    % 1 0 0 1 1 1 0 1
    % . . . . . . . .
    % <samples_per_bit times>
    % . . . . . . . .
    % 1 0 0 1 1 1 0 1
    %
    % This is mainly because there's (amazingly) not a good/easy way to do
    % it in MATLAB.

    for k = 1:m
        temp = repmat( msg(k,:), samples_per_symbol, 1);

        % So it takes two steps to perform our oversample of the data.
        % This function reshapes that matrix of data by running
        % down the columns and placing the data into a single long vector, thus
        % accomplishing the goal of replicating the bits samples_per_bit times.
        %
        % In FSK, we need a vector of low and high frequency multiplicands.
        % We'll map our msg to 1->2 and then multiply that by our chosen
        % frequency (in this case 200 Hz) so that our message will vary between
        % 200 and 400 Hz.
        phi = (reshape( temp, samples_per_symbol*n, 1) + 1)*f;

        % In FSK, the frequency of the carrier is what the message modulates.
        % i.e. it's the frequency of the sinusoid which carries the
        % information.
        modulated(k,:) = sin( phi .* t' )';
    end

Plot the results in a pretty little display... with titles!

    if doplot == 1
        % Plot the results
        h1 = figure;             % Create a new plot figure
        h2 = figure;             % Create a new plot figure
        for k = 1:m
            figure(h1);
            subplot( 2,1,1 );           % Create a subplot frame inside the figure with
                                        % 2 horizontal plots
            plot( modulated(k,:) );     % plot the modulated data

            % Set the axes limits for the y axis... cause I HATE how MATLAB does
            % this by default.
            ylim( [(min(modulated(k,:)) - 0.5) (max(modulated(k,:) + 0.5))] );
            str = sprintf( 'FSK Modulated Message : %d of %d', k, m );
            title( str );               % Give it a title.

            subplot(2,1,2);             % Move to the next frame in the subplot
            msg(k,:) = msg(k,:);
            plot( msg(k,:) );           % Plot our msg, remembering to subtract 1 to make
                                        % it 0->1 bits instead of 1->2

            % Set the ylimit so you can see the top of the msg bits... otherwise
            % they're unviewable.
            ylim( [(min(msg(k,:)) - 0.5) (max(msg(k,:)) + 0.5)] );
            str = sprintf( 'Original Message Bits : Message %d of %d', k, m );
            title( str );               % Give it a title.

            figure(h2);
            Hz = -samples_per_symbol/2:samples_per_symbol/length(modulated(k,:)):samples_per_symbol/2;
            Hz = Hz(1:length(modulated(k,:)));
            plot(Hz, abs(fftshift(fft(modulated(k,:)))))
            title('FSK Spectrogram');
            xlabel('Hz');
            % Since it's a real-valued signal, the spectrogram is symmetric about
            % 0 Hz.
            xlim( [-10 10] );

            if k ~= m
                fprintf( 'Press space bar or enter to move on to the next plot\n' );
                pause;
            end
        end
    end
end

Contact us