1 ## Copyright (C) 2003 David Bateman
3 ## This program is free software; you can redistribute it and/or modify it under
4 ## the terms of the GNU General Public License as published by the Free Software
5 ## Foundation; either version 3 of the License, or (at your option) any later
8 ## This program is distributed in the hope that it will be useful, but WITHOUT
9 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 ## You should have received a copy of the GNU General Public License along with
14 ## this program; if not, see <http://www.gnu.org/licenses/>.
17 ## @deftypefn {Function File} {} qaskenco (@var{m})
18 ## @deftypefnx {Function File} {} qaskenco (@var{msg},@var{m})
19 ## @deftypefnx {Function File} {@var{y} = } qaskenco (@var{...})
20 ## @deftypefnx {Function File} {[@var{inphase}, @var{quadr}] =} qaskenco (@var{...})
22 ## Map a digital signal using a square QASK constellation. The argument
23 ## @var{m} must be a positive integer power of 2. With two input arguments
24 ## the variable @var{msg} represents the message to be encoded. The values
25 ## of @var{msg} must be between 0 and @code{@var{m}-1}. In all cases
26 ## @code{qaskenco(@var{M})} is equivalent to @code{qaskenco(1:@var{m},@var{m})}
28 ## Three types of outputs can be created depending on the number of output
32 ## @item No output arguments
33 ## In this case @dfn{qaskenco} plots the constellation. Only the
34 ## points in @var{msg} are plotted, which in the case of a single input
35 ## argument is all constellation points.
36 ## @item A single output argument
37 ## The returned variable is a complex variable representing the in-phase
38 ## and quadrature components of the mapped message @var{msg}. With, a
39 ## single input argument this effectively gives the mapping from symbols
40 ## to constellation points
41 ## @item Two output arguments
42 ## This is the same as two ouput arguments, expect that the in-phase
43 ## and quadrature components are returned explicitly. That is
46 ## octave> c = qaskenco(msg, m);
47 ## octave> [a, b] = qaskenco(msg, m);
48 ## octave> all(c == a + 1i*b)
53 ## If @code{sqrt(@var{m})} is an integer, then @dfn{qaskenco} uses a Gray
54 ## mapping. Otherwise, an attempt is made to create a nearly square mapping
55 ## with a minimum Hamming distance between adjacent constellation points.
59 ## 2005-04-23 Dmitri A. Sergatskov <dasergatskov@gmail.com>
60 ## * modified for new gnuplot interface (octave > 2.9.0)
62 function [a, b] = qaskenco(msg, M)
67 if ((min(msg(:)) < 0) || (max(msg(:)) > M-1))
68 error ("qaskenco: message invalid");
71 error ("qaskenco: incorrect number of arguments");
74 if (!isscalar(M) || (M != ceil(M)) || (M < 2))
75 error ("qaskenco: order of modulation must be a positive integer greater than 2");
78 if (log2(M) != ceil(log2(M)))
79 error ("qaskenco: the order must be a power of two");
86 inphase = [-1, -1, 1, 1];
87 quadr = [-1, 1, -1, 1];
89 inphase = [-1, -1, 1, 1, -3, -3, 3, 3];
90 quadr = [-1, 1, -1, 1, -1, 1, -1, 1];
92 NC =2^floor(log2(sqrt(M)));
95 for i=2:ceil(log2(NC))
96 Gray = [Gray 2^(i-1) + fliplr(Gray)];
98 Gray = fliplr(de2bi(shift(Gray,length(Gray)/2 - 1)));
99 Gray2 = zeros(MM,log2(MM));
100 Gray2(:,1:2:log2(MM)) = repmat(Gray,NC,1);
102 Gray2(i:NC:MM,2:2:log2(MM)) = Gray;
104 layout = reshape(bi2de(fliplr(Gray2)),NC,NC);
107 ## Not sure this is the best that can be done for these mappings. If
108 ## anyone wants to improve this, go ahead, but do it in qaskdeco too.
111 layout2 = NaN * ones(NR);
112 layout2(1+OFF:OFF+NC,1+OFF:OFF+NC) = layout;
114 layout2(1:OFF,1+OFF:OFF+NC) = MM + layout(OFF:-1:1,:);
115 layout2(NR-OFF+1:NR,1+OFF:OFF+NC) = MM + layout(NC:-1:NC-OFF+1,:);
117 layout2(1+2*OFF:NC,1:OFF) = MM + layout(OFF+1:NC-OFF,OFF:-1:1);
118 layout2(1+2*OFF:NC,NR-OFF+1:NR) = MM + ...
119 layout(OFF+1:NC-OFF,NC:-1:NC-OFF+1);
121 layout2(1+OFF:2*OFF,1:OFF) = MM + ...
122 layout(NC/2:-1:NC/2-OFF+1,NC/2:-1:OFF+1);
123 layout2(NC+1:OFF+NC,1:OFF) = MM + ...
124 layout(NC-OFF:-1:NC/2+1,NC/2:-1:OFF+1);
126 layout2(1+OFF:2*OFF,NR-OFF+1:NR) = MM + ...
127 layout(NC/2:-1:NC/2-OFF+1,NC-OFF:-1:NC/2+1);
128 layout2(NC+1:OFF+NC,NR-OFF+1:NR) = MM + ...
129 layout(NC-OFF:-1:NC/2+1,NC-OFF:-1:NC/2+1);
134 inphase = repmat([0:NC-1]*2 - NC + 1,1,NC);
136 quadr(i:NC:NC*NC) = [0:NC-1]*2 - NC + 1;
138 [dummy, indx] = sort(layout(:));
139 indx = indx(1:M); ## Get rid of remaining NaN's
140 inphase = inphase(indx);
145 inphase = inphase(msg+1);
146 quadr = quadr(msg+1);
147 ## Fix up indexing if using column vector
148 if (size(msg,2) == 1)
155 inphase = inphase(:);
157 plot (inphase, quadr, "r+");
158 title("QASK Constellation");
160 ylabel("Quadrature");
161 axis([min(inphase)-1, max(inphase)+1, min(quadr)-1, max(quadr)+1]);
162 xd = 0.02 * max(inphase);
165 for i=1:length(inphase)
166 text(inphase(i)+xd,quadr(i),num2str(msg(i)));
169 for i=1:length(inphase)
170 text(inphase(i)+xd,quadr(i),num2str(i-1));
173 elseif (nargout == 1)
174 a = inphase + 1i * quadr;