]> Creatis software - CreaPhase.git/blobdiff - octave_packages/communications-1.1.1/modmap.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / communications-1.1.1 / modmap.m
diff --git a/octave_packages/communications-1.1.1/modmap.m b/octave_packages/communications-1.1.1/modmap.m
new file mode 100644 (file)
index 0000000..147ef63
--- /dev/null
@@ -0,0 +1,332 @@
+## 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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- 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
+
+  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!!!
+      try stem ([0, fd], [2, 1]);
+      catch
+       error ("modmap: can not find stem-plot function");
+      end
+      title("MSK constellation");
+      xlabel("Frequency (Hz)");
+      ylabel("");
+      axis([-fd, 2*fd, 0, 2]);
+    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!!!
+      try stem ([0:tone:(M-1)*tone], [2, ones(1,M-1)]);
+      catch
+       error ("modmap: can not find stem-plot function");
+      end
+      title("FSK constellation");
+      xlabel("Frequency (Hz)");
+      ylabel("");
+      axis([-tone, M*tone, 0, 2]);
+    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)
+      inphase = inphase(:);
+      quadr = quadr(:);
+      plot (inphase, quadr, "+r");
+      title("QASK Constellation");
+      xlabel("In-phase");
+      ylabel("Quadrature");
+      axis([min(inphase)-1, max(inphase)+1, min(quadr)-1, max(quadr)+1]);
+      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
+      refresh;
+    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