]> Creatis software - CreaPhase.git/blob - octave_packages/communications-1.1.1/qaskenco.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / communications-1.1.1 / qaskenco.m
1 ## Copyright (C) 2003 David Bateman
2 ##
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
6 ## version.
7 ##
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
11 ## details.
12 ##
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/>.
15
16 ## -*- texinfo -*-
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{...})
21 ##
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})}
27 ##
28 ## Three types of outputs can be created depending on the number of output 
29 ## arguments. That is
30 ##
31 ## @table @asis
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
44 ##
45 ## @example
46 ## octave> c = qaskenco(msg, m);
47 ## octave> [a, b] = qaskenco(msg, m);
48 ## octave> all(c == a + 1i*b)
49 ## ans = 1
50 ## @end example
51 ## @end table
52 ##
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.
56 ## @end deftypefn
57 ## @seealso{qaskdeco}
58
59 ## 2005-04-23 Dmitri A. Sergatskov <dasergatskov@gmail.com>
60 ##     * modified for new gnuplot interface (octave > 2.9.0)
61
62 function [a, b] = qaskenco(msg, M)
63
64   if (nargin == 1)
65     M = msg;
66   elseif (nargin == 2)
67     if ((min(msg(:)) < 0) || (max(msg(:)) > M-1))
68       error ("qaskenco: message invalid");
69     endif
70   else
71     error ("qaskenco: incorrect number of arguments");
72   endif
73
74   if (!isscalar(M) || (M != ceil(M)) || (M < 2))
75     error ("qaskenco: order of modulation must be a positive integer greater than 2");
76   endif
77
78   if (log2(M) != ceil(log2(M)))
79     error ("qaskenco: the order must be a power of two");
80   endif
81   
82   if (M == 2)
83     inphase = [-1,  1];
84     quadr =   [ 0,  0];
85   elseif (M == 4)
86     inphase = [-1, -1,  1,  1];
87     quadr =   [-1,  1, -1,  1];
88   elseif (M == 8)
89     inphase = [-1, -1,  1,  1, -3, -3,  3,  3];
90     quadr =   [-1,  1, -1,  1, -1,  1, -1,  1];
91   else
92     NC =2^floor(log2(sqrt(M)));
93     MM = NC * NC;
94     Gray = [0, 1];
95     for i=2:ceil(log2(NC))
96       Gray = [Gray 2^(i-1) + fliplr(Gray)];
97     end
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);
101     for i=1:NC
102       Gray2(i:NC:MM,2:2:log2(MM)) = Gray;
103     end
104     layout = reshape(bi2de(fliplr(Gray2)),NC,NC);
105
106     if (MM != M)
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.
109       OFF = sqrt(M/32);
110       NR = NC + 2*OFF;
111       layout2 = NaN * ones(NR);
112       layout2(1+OFF:OFF+NC,1+OFF:OFF+NC) = layout;
113       
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,:);
116
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);
120
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);
125
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);
130       NC = NR;
131       layout = layout2;
132     endif
133
134     inphase = repmat([0:NC-1]*2 - NC + 1,1,NC);
135     for i=1:NC
136       quadr(i:NC:NC*NC) = [0:NC-1]*2 - NC + 1;
137     end
138     [dummy, indx] = sort(layout(:));
139     indx = indx(1:M);                   ## Get rid of remaining NaN's
140     inphase = inphase(indx);
141     quadr = quadr(indx);
142   endif
143
144   if (nargin == 2)
145     inphase = inphase(msg+1);
146     quadr = quadr(msg+1);
147     ## Fix up indexing if using column vector
148     if (size(msg,2) == 1)
149       inphase = inphase';
150       quadr = quadr';
151     endif
152   endif
153
154   if (nargout == 0)
155     inphase = inphase(:);
156     quadr = quadr(:);
157     plot (inphase, quadr, "r+");
158     title("QASK Constellation");
159     xlabel("In-phase");
160     ylabel("Quadrature");
161     axis([min(inphase)-1, max(inphase)+1, min(quadr)-1, max(quadr)+1]);
162     xd = 0.02 * max(inphase);
163     if (nargin == 2)
164       msg = msg(:);
165       for i=1:length(inphase)
166         text(inphase(i)+xd,quadr(i),num2str(msg(i)));
167       end
168     else
169       for i=1:length(inphase)
170         text(inphase(i)+xd,quadr(i),num2str(i-1));
171       end
172     endif
173   elseif (nargout == 1)
174     a = inphase + 1i * quadr;
175   else
176     a = inphase;
177     b = quadr;
178   endif
179
180 endfunction