function DPSKSymbols = DPSK( PAMSymbols, phi0, theta0 )
% DPSK - convert PAM symbols to differentially phase encoded symbols
%
% DPSK allows information to be differentially phase encoded. Assume that
% the n-th element vector PAMSymbols has the value xn, then the  n-th
% symbol will have phase difference dtheta_n = phi0*xn.
%
% The PAMSymbols and phase offset phi0 must be chosen to match. Two cases
% make sense:
%
%   1. PAMSymbols drawn form 0:M-1, then phi_0 should be 2*pi/M
%   2. PAMSymbols drawn from -(M-1):2:(M-1), then phi_0 should be pi/M
%
% The second case leads to the use of offset constellations that are
% beneficial for reducing magnitude variations.
%
% Inputs:
%   PAMSymbols - vector of PAM encoded symbols (according to two cases
%                above)
%   phi0       - phase offset
%   theta_0    - initial phase (defaults to 0)
%
% Output:
%   DPSKSymbols - vector of DPSK symbols (one longer than PAMSymbols,
%                 initial symbol has phase theta_0)
%
% Example:
%   DPSKSymbols = DPSK( PAMSymbols, phi0, theta0 )
%   DPSKSymbols = DPSK( PAMSymbols, phi0) % theta0 = 0

%% check if theta0 is provided
if ( nargin < 3)
    theta0 = 0;
end

%% accumulate phase differences, then convert to complex symbols
Phases      = cumsum( [theta0 phi0*PAMSymbols] );
DPSKSymbols = exp( j*Phases );
