## Copyright (C) 2003 David Bateman ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## -*- texinfo -*- ## @deftypefn {Function File} {} modmap (@var{method},@var{...}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'ask',@var{m}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'fsk',@var{m},@var{tone}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'msk') ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'psk',@var{m}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'qask',@var{m}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'qask/cir',@var{nsig},@var{amp},@var{phs}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'qask/arb',@var{inphase},@var{quadr}) ## @deftypefnx {Function File} {y = } modmap (@var{x},@var{fd},@var{fs},'qask/arb',@var{map}) ## ## Mapping of a digital signal to an analog signal. With no output arguments ## @dfn{modmap} plots the constellation of the mapping. In this case the ## first argument must be the string @var{method} defining one of 'ask', ## 'fsk', 'msk', 'qask', 'qask/cir' or 'qask/arb'. The arguments following ## the string @var{method} are generally the same as those after the ## corresponding string in the fucntion call without output arguments. ## The exception is @code{modmap('msk',@var{Fd})}. ## ## With an output argument, @var{y} is the complex mapped analog signal. In ## this case the arguments @var{x}, @var{fd} and @var{fs} are required. The ## variable @var{x} is the digital signal to be mapped, @var{fd} is the ## sampling rate of the of digital signal and the @var{fs} is the sampling ## rate of the analog signal. It is required that @code{@var{fs}/@var{fd}} ## is an integer. ## ## The available mapping of the digital signal are ## ## @table @asis ## @item 'ask' ## Amplitude shift keying ## @item 'fsk' ## Frequency shift keying ## @item 'msk' ## Minimum shift keying ## @item 'psk' ## Phase shift keying ## @item 'qask' ## @itemx 'qsk' ## @itemx 'qam' ## Quadraure amplitude shift keying ## @end table ## ## In addition the 'qask', 'qsk' and 'qam' method can be modified with the ## flags '/cir' or '/arb'. That is 'qask/cir' and 'qask/arb', etc are valid ## methods and give circular- and arbitrary-qask mappings respectively. ## ## The additional argument @var{m} is the order of the modulation to use. ## @var{m} must be larger than the largest element of @var{x}. The variable ## @var{tone} is the FSK tone to use in the modulation. ## ## For 'qask/cir', the additional arguments are the same as for ## @dfn{apkconst}, and you are referred to @dfn{apkconst} for the definitions ## of the additional variables. ## ## For 'qask/arb', the additional arguments @var{inphase} and @var{quadr} give ## the in-phase and quadrature components of the mapping, in a similar mapping ## to the outputs of @dfn{qaskenco} with one argument. Similar @var{map} ## represents the in-phase and quadrature components of the mapping as ## the real and imaginary parts of the variable @var{map}. ## @end deftypefn ## @seealso{demodmap,dmodce,amodce,apkconst,qaskenco} function y = modmap(varargin) method = "sample"; if (nargout == 0) if (nargin < 1) error ("modmap: too few arguments"); endif method = varargin{1}; optarg = 1; M = 2; fd = 1; fs = 1; elseif (nargout == 1) if (nargin < 3) error ("modmap: too few arguments"); endif x = varargin{1}; fd = varargin{2}; fs = varargin{3}; if (nargin > 3) method = varargin{4}; endif M = max(2,2^ceil(log2(max(x(:)) + 1))); optarg = 4; if (!isscalar(fs) || !isscalar(fd) || !isreal(fs) || !isreal(fd) || ... (fs <= 0) || (fd <= 0)) error ("modmap: sampling rates must be positive real values"); endif if (abs(fs/fd - floor(fs/fd)) > eps) error ("modmap: the sample rate Fs must be an integer multiple of Fd"); endif nn = round(fs/fd); if (min(size(x)) == 1) n = length(x); yy = zeros(n,1); if (size(x,1) == 1) yy = yy'; end for i=1:nn yy(i:nn:nn*n) = x; end else n = size(x,1); yy = zeros(n*nn,size(x,2)); for i=1:nn yy(i:nn:nn*n,:) = x; end endif x = yy; else error ("modmap: too many output arguments"); endif if (!ischar(method)) error ("modmap: mapping method to use must be a string"); endif if (isempty(findstr(method,"/arb")) && isempty(findstr(method,"/cir"))) if (nargin > optarg) M = varargin{optarg+1}; if (!isscalar(M) || !isreal(M) || (M < 0) || (M != floor(M))) error ("modmap: modulation order must be a real positive integer"); endif endif if ((nargout != 0) && (M < max(x(:)) + 1)) error ("modmap: illegal symbol in data for modulation order"); endif endif try ar = automatic_replot; catch ar = 0; end if (strcmp(method,"ask")) if (nargin > optarg + 1) error ("modmap: too many arguments"); endif if (nargout == 0) if (floor(M/2) == M/2) apkconst(2*ones(1,M/2),2*([1:M/2]-0.5)/(M-1)); else apkconst([1,2*ones(1,floor(M/2))],2*([0:floor(M/2)])/(M-1)); endif else if (floor(M/2) == M/2) c = [ -2*([M/2:-1:1]-0.5)/(M-1), 2*([1:M/2]-0.5)/(M-1)]; else c = [ -2*([floor(M/2):-1:1])/(M-1), 0, 2*([1:floor(M/2)])/(M-1)]; endif y = c(x+1); if (size(x,2) == 1) y = y'; endif endif elseif (strcmp(method,"psk")) if (nargin > optarg + 1) error ("modmap: too many arguments"); endif if (nargout == 0) apkconst(M,"n"); else c = apkconst(M); y = c(x+1); if (size(x,2) == 1) y = y'; endif endif elseif (strcmp(method,"msk")) if (nargout == 0) if (nargin > optarg) fd = varargin{optarg+1}; if (!isscalar(fd)) error ("modmap: the sampling rate must be a scalar"); endif endif if (nargin > optarg + 1) error ("modmap: too many arguments"); endif ## This is an ugly plot, with little info. But hey!!! unwind_protect title("MSK constellation"); xlabel("Frequency (Hz)"); ylabel(""); axis([-fd, 2*fd, 0, 2]); try stem ([0, fd], [2, 1]); catch error ("modmap: can not find stem-plot function"); end unwind_protect_cleanup xlabel(""); ylabel(""); title(""); __gnuplot_set__ autoscale; hold off; automatic_replot = ar; end_unwind_protect else if (nargin > optarg) error ("modmap: too many arguments"); endif tone = fd/2; y = tone * x; endif elseif (strcmp(method,"fsk")) if (nargin > optarg + 1) tone = varargin{optarg+2}; if (!isscalar(tone)) error ("modmap: the FSK tone must be a scalar"); endif else tone = fd; endif if (nargin > optarg + 2) error ("modmap: too many arguments"); endif if (nargout == 0) ## This is an ugly plot, with little info. But hey!!! unwind_protect title("FSK constellation"); xlabel("Frequency (Hz)"); ylabel(""); axis([-tone, M*tone, 0, 2]); try stem ([0:tone:(M-1)*tone], [2, ones(1,M-1)]); catch error ("modmap: can not find stem-plot function"); end unwind_protect_cleanup xlabel(""); ylabel(""); title(""); __gnuplot_set__ autoscale; hold off; automatic_replot = ar; end_unwind_protect else y = tone * x; endif elseif ((strcmp(method,"qask")) || (strcmp(method,"qsk")) || ... (strcmp(method,"qam"))) if (nargin > optarg + 1) error ("modmap: too many arguments"); endif if (nargout == 0) qaskenco(M); else y = qaskenco(x, M); endif elseif ((strcmp(method,"qask/cir")) || (strcmp(method,"qsk/cir")) || ... (strcmp(method,"qam/cir"))) nsig = M; amp = []; phs = []; if (nargin > optarg) nsig = varargin{optarg+1}; if (!isvector(nsig) || (sum(nsig) < M)) error ("modmap: insufficient number of constellation point in qask/cir"); endif endif if (nargin > optarg + 1) amp = varargin{optarg+2}; endif if (nargin > optarg + 2) phs = varargin{optarg+3}; endif if (nargout == 0) apkconst(nsig,amp,phs,"n"); else c = apkconst(nsig,amp,phs); y = c(x+1); if (size(x,2) == 1) y = y'; endif endif elseif ((strcmp(method,"qask/arb")) || (strcmp(method,"qsk/arb")) || ... (strcmp(method,"qam/arb"))) if (nargin == optarg) [inphase, quadr] = qaskenco(M); elseif (nargin == optarg+1) c = varargin{optarg+1}; inphase = real(c); quadr = imag(c); elseif (nargin == optarg+2) inphase = varargin{optarg+1}; quadr = varargin{optarg+2}; else error ("modmap: incorrectly defined mapping in 'qask/arb'"); endif if (!isreal(inphase) || !isreal(quadr) || !isvector(inphase) || ... !isvector(quadr) || !all(isfinite(inphase)) || ... !all(isfinite(quadr)) ||(length(inphase) < M)) error ("modmap: invalid arbitrary qask mapping"); endif if (nargout == 0) unwind_protect inphase = inphase(:); quadr = quadr(:); clearplot; title("QASK Constellation"); xlabel("In-phase"); ylabel("Quadrature"); axis([min(inphase)-1, max(inphase)+1, min(quadr)-1, max(quadr)+1]); __gnuplot_set__ nokey; hold off; yy = [inphase, quadr]; eval("__gnuplot_plot__ yy w p 1;"); hold on; xd = 0.02 * max(inphase); if (nargin == 2) msg = msg(:); for i=1:length(inphase) text(inphase(i)+xd,quadr(i),num2str(msg(i))); end else for i=1:length(inphase) text(inphase(i)+xd,quadr(i),num2str(i-1)); end endif replot; unwind_protect_cleanup xlabel(""); ylabel(""); title(""); __gnuplot_set__ autoscale; hold off; text(); automatic_replot = ar; end_unwind_protect else y = inphase(x+1) + 1i * quadr(x+1); if (size(x,2) == 1) y = y'; endif endif elseif (strcmp(method,"sample")) if (nargout == 0) error ("modmap: no constellation for resampling"); endif ## Just for resampling !!! So don't need anything else here y = x; else error ("modmap: unknown mapping method"); endif endfunction