Robochameleon  v1.0
pwr.m
Go to the documentation of this file.
1 classdef pwr
2 
3  properties (SetAccess=immutable,Hidden=true)
4  P_dBW;
5  SNR_dB;
6  end
7 
8  methods (Access=private,Hidden=true,Static=true)
9 
10  function res = validpwr(P)
11  res = false;
12  if isscalar(P) && isreal(P), res = true; end
13  end
14 
15  function P_format = outputP(P_dBW,varargin)
16  type = defaultargs('dBm',varargin{:});
17  switch lower(type)
18  case 'w'
19  P_format = dB2lin(P_dBW);
20  case 'mw'
21  P_format = dB2lin(P_dBW)*1e3;
22  case 'uw'
23  P_format = dB2lin(P_dBW)*1e6;
24  case 'dbw'
25  P_format = P_dBW;
26  case 'dbm'
27  P_format = P_dBW+30;
28  case 'dbu'
29  P_format = P_dBW+60;
30  otherwise
31  error('Power unit can be W, mW, uW, dBW, dBm or dBu.');
32  end
33  end
34 
35  function SNR_format = outputSNR(SNR_dB,varargin)
36  type = defaultargs('dB',varargin{:});
37  switch lower(type)
38  case 'lin'
39  SNR_format = dB2lin(SNR_dB);
40  case 'db'
41  SNR_format = SNR_dB;
42  otherwise
43  error('SNR unit can be lin for linear or dB.');
44  end
45  end
46 
47  function P_dB = inputP(P)
48  if pwr.validpwr(P)
49  type = 'dBm';
50  elseif iscell(P) && numel(P)==2 && pwr.validpwr(P{1}) && ischar(P{2})
51  type = lower(P{2});
52  P = P{1};
53  else
54  error('Power must be specified as a real scalar (in dBm) or a cell array must be constructed as {value,unit}');
55  end
56  switch lower(type)
57  case 'w'
58  P_dB = lin2dB(P);
59  case 'mw'
60  P_dB = lin2dB(P/1e3);
61  case 'uw'
62  P_dB = lin2dB(P/1e6);
63  case 'dbw'
64  P_dB = P;
65  case 'dbm'
66  P_dB = P-30;
67  case 'dbu'
68  P_dB = P-60;
69  otherwise
70  error('Power unit can be W, mW, uW, dBW, dBm or dBu.');
71  end
72  end
73 
74  function SNR_dB = inputSNR(SNR)
75  if pwr.validpwr(SNR)
76  type = 'dB';
77  elseif iscell(SNR) && numel(SNR)==2 && pwr.validpwr(SNR{1}) && ischar(SNR{2})
78  type = lower(SNR{2});
79  SNR = SNR{1};
80  else
81  error('SNR must be specified as a real scalar (in dB) or a cell array must be constructed as {value,unit}.');
82  end
83  switch lower(type)
84  case 'lin'
85  SNR_dB = lin2dB(SNR);
86  case 'db'
87  SNR_dB = SNR;
88  otherwise
89  error('SNR unit can be lin for linear or dB.');
90  end
91  end
92 
93 
94 
95  end
96 
97  methods (Static=true)
98 
99  function [y,scfactor] = normpwr(x,varargin)
100  [type,P,unit] = defaultargs({'average',1,'linear'},varargin);
101 
102  switch lower(unit)
103  case {'linear','lin'}
104  P_ = P;
105 
106  case {'db'}
107  P_ = 10^(P/10);
108 
109  case {'dbm'}
110  P_ = 1e-3*10^(P/10);
111 
112  otherwise
113  error('Unit must be ''linear'', ''dB'' or ''dBm''.');
114  end
115 
116  % TODO Handling real and complex cases
117  [Pav,~,Prange] = pwr.meanpwr(x(:));
118  switch lower(type)
119  case {'average','avg'}
120  scfactor = Pav/P_;
121 
122  case {'maximum','max'}
123  scfactor = Prange(2,:)/P_;
124 
125  otherwise
126  error('Normalization type must be ''average'' or ''maximum''.');
127  end
128 
129 % y = bsxfun(@mrdivide,x,sqrt(scfactor));
130  y = x/sqrt(scfactor);
131  end
132 
133  function [P,E,Prange,Ppeak] = meanpwr(x)
134 
135  if isvector(x)
136  L = numel(x);
137  else
138  L = size(x,1);
139  end
140  %absxsq = abs(x).^2;
141  absxsq = x.*conj(x); %faster
142  Ppeak = max(absxsq);
143  E = sum(absxsq);
144 % if isreal(x)
145 % E = E/2;
146 % end
147  P = E/L;
148  Prange = findrange(absxsq);
149  end
150 
151  function OSNR = getOSNR(sig, varargin)
152  if nargin < 3
153  NBW = 0.1;
154  else
155  NBW = varargin{2};
156  end
157  if sig.Fc == 0
158  robolog('The signal carrier frequency is required to compute the noise bandwidth', 'ERR');
159  end
160  lambda = const.c/sig.Fc;
161  NBW_Hz = const.c./(lambda-.5*1e-9*NBW)-const.c./(lambda+.5*1e-9*NBW);
162  OSNR_dB = sig.P.SNR+10*log10(sig.Fs/NBW_Hz);
163  if nargin > 1
164  OSNR = pwr.outputSNR(OSNR_dB,varargin(1));
165  else
166  OSNR = pwr.outputSNR(OSNR_dB,{});
167  end
168  end
169 
170  end
171 
172  methods
173 
174  function obj = pwr(SNR,P)
175  if nargin<1
176  error('Signal-to-noise ratio must be specified.');
177  elseif nargin<2
178  P = 0;
179  end
180  obj.SNR_dB = pwr.inputSNR(SNR);
181  obj.P_dBW = pwr.inputP(P);
182  end
183 
184  function obj = plus_1elem(obj1,obj2)
185  Ps = obj1.Ps('W')+obj2.Ps('W');
186  Pn = obj1.Pn('W')+obj2.Pn('W');
187  %zero total power is a special case
188  if isinf(log10(Ps))&&isinf(log10(Pn))
189  obj = pwr(0, -Inf);
190  else
191  obj = pwr({Ps/Pn,'lin'},{Ps+Pn,'W'});
192  end
193  end
194 
195  function obj = plus(obj1, obj2)
196  if numel(obj1)~=numel(obj2)
197  error('When adding two power object arrays, number of elements in array 1 must equal number of elements in array 2');
198  end
199  obj = plus_1elem(obj1(1), obj2(1));
200  for jj=2:numel(obj1)
201  obj(jj) = plus_1elem(obj1(jj), obj2(jj));
202  end
203 
204  end
205 
206  function obj = minus(obj1,obj2)
207  warning('Subtraction is equivalent to addition -- no correlation.')
208  obj = plus(obj1,obj2);
209  end
210 
211  function obj = mtimes(in1,in2)
212  if isa(in1, 'pwr')&&~isa(in2, 'pwr')
213  Ps = dB2lin([in1.P_dBW])*in2;
214  SNR = [in1.SNR_dB];
215  elseif ~isa(in1, 'pwr')&&isa(in2, 'pwr')
216  Ps = in1*dB2lin([in2.P_dBW]);
217  SNR = [in2.SNR_dB];
218  end
219  for jj=1:numel(Ps)
220  obj(jj) = pwr(SNR(jj), {Ps(jj), 'W'});
221  end
222  end
223 
224  function obj = times(in1, in2)
225  if numel(in1)==numel(in2)
226  for jj=1:numel(in1), obj(jj) = in1(jj)*in2(jj); end
227  elseif (numel(in1)==1)||(numel(in2)==1)
228  if numel(in1)==1
229  for jj=1:numel(in2), obj(jj) = in1*in2(jj); end
230  else
231  for jj=1:numel(in1), obj(jj) = in1(jj)*in2; end
232  end
233  else
234  error('Matrix dimensions must agree');
235  end
236  end
237 
238  function obj = mrdivide(in1, C)
239  obj = mtimes(in1, 1/C);
240  end
241 
242  function P = P(obj,varargin)
243  warning('Please use Ptot instead of P function of pwr.');
244  P = Ptot(obj,varargin{:});
245  end
246 
247  function SNR = SNR(obj,varargin)
248  SNR = pwr.outputSNR(obj.SNR_dB,varargin);
249  end
250 
251  function Ptot = Ptot(obj,varargin)
252  Ptot = pwr.outputP(obj.P_dBW,varargin);
253  end
254 
255  function Ps = Ps(obj,varargin)
256  if isinf(obj.SNR('lin')) % If SNR is infinite, there is no noise, so Ps = P;
257  Ps = obj.Ptot('dBW');
258  else
259  Ps = obj.Ptot('dBW')+obj.SNR('dB')-10*log10(obj.SNR('lin')+1);
260  end
261  Ps = pwr.outputP(Ps,varargin);
262  end
263 
264  function Pn = Pn(obj,varargin)
265  Pn = pwr.outputP(obj.Ptot('dBW')-10*log10(obj.SNR('lin')+1),varargin);
266  end
267 
268  function obj = disp(obj)
269  % Space pad differently to show single power object
270  % or array (PCol)
271  if numel(obj) == 1
272  spacePad = ' ';
273  else
274  spacePad = '';
275  end
276  print_obj = @(obj)fprintf(1,'%s Total power: %1.2f dBm (%1.2f mW)\n%s SNR: %1.2f dB (%1.2f)\n%s Signal power: %1.2f dBm (%1.2f mW)\n%s Noise power: %1.2f dBm (%1.2f mW)\n',...
277  spacePad,obj.Ptot('dBm'),obj.Ptot('mW'),spacePad,obj.SNR('dB'),obj.SNR('lin'),spacePad,obj.Ps('dBm'),obj.Ps('mW'),spacePad,obj.Pn('dBm'),obj.Pn('mW'));
278  if numel(obj)==1
279  print_obj(obj);
280  else
281  % Used when we want to print PCol (array of pwr objects)
282  for jj=1:numel(obj)
283  fprintf(1, 'Power in signal %d:\n', jj);
284  print_obj(obj(jj))
285  fprintf(1, '\n');
286  end
287  end
288  end
289 
290  end
291 
292 end
static function inputSNR(in SNR)
Parse format to set SNR.
Superclass: basic building block to hold functions.
Definition: unit.m:27
power description class
Definition: pwr.m:27
function findrange(in x)
Finds min-max range of a vector/matrix.
static function outputP(in P_dBW, in varargin)
Parse format to get power.
static function outputSNR(in SNR_dB, in varargin)
Parse format to get SNR.
function lin2dB(in lin, in varargin)
Convert linear units to dB.
static function validpwr(in P)
validate power
function robolog(in msg, in varargin)
This function allows the user to print log messages in a standard way.
static function inputP(in P)
Parse format to set power.
static function meanpwr(in x)
Mean signal power and energy.
function dB2lin(in dB, in varargin)
Convert dB to linear units.