My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
qucsfilter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qucsfilter.cpp
3  ----------------
4  begin : Wed Mar 02 2005
5  copyright : (C) 2005 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <math.h>
23 #include <stdlib.h>
24 #include <string>
25 
26 #include <qmenubar.h>
27 #include <qpopupmenu.h>
28 #include <qmessagebox.h>
29 #include <qlayout.h>
30 #include <qlabel.h>
31 #include <qpushbutton.h>
32 #include <qlineedit.h>
33 #include <qcombobox.h>
34 #include <qvalidator.h>
35 #include <qtimer.h>
36 #include <qclipboard.h>
37 #include <qapplication.h>
38 
39 #include "lc_filter.h"
40 #include "qf_poly.h"
41 #include "qf_filter.h"
42 #include "qf_cauer.h"
43 #include "qucsfilter.h"
44 #include "helpdialog.h"
45 
47 {
48  // set application icon
49  setIcon (QPixmap(QucsSettings.BitmapDir + "big.qucs.xpm"));
50  setCaption("Qucs Filter " PACKAGE_VERSION);
51 
52 
53  // -------- create menubar -------------------
54  QPopupMenu *fileMenu = new QPopupMenu();
55  fileMenu->insertItem(tr("E&xit"), this, SLOT(slotQuit()), CTRL+Key_Q);
56 
57  QPopupMenu *helpMenu = new QPopupMenu();
58  helpMenu->insertItem(tr("Help..."), this, SLOT(slotHelpIntro()), Key_F1);
59  helpMenu->insertSeparator();
60  helpMenu->insertItem(
61  tr("&About QucsFilter..."), this, SLOT(slotHelpAbout()), 0);
62  helpMenu->insertItem(tr("About Qt..."), this, SLOT(slotHelpAboutQt()), 0);
63 
64  QMenuBar *bar = new QMenuBar(this);
65  bar->insertItem(tr("&File"), fileMenu);
66  bar->insertSeparator ();
67  bar->insertItem(tr("&Help"), helpMenu);
68 
69 
70  // ------- create main windows widgets --------
71  gbox = new QGridLayout(this, 10,3,5,5);
72 
73  QWidget *Space = new QWidget(this); // reserve space for menubar
74  Space->setFixedSize(5, bar->height());
75  gbox->addWidget(Space, 0,0);
76 
77  QLabel *Label1 = new QLabel(tr("Filter type:"), this);
78  gbox->addWidget(Label1, 1,0);
79  ComboType = new QComboBox(this);
80  ComboType->insertItem("Bessel");
81  ComboType->insertItem("Butterworth");
82  ComboType->insertItem("Chebyshev");
83  ComboType->insertItem("Cauer");
84  gbox->addWidget(ComboType, 1,1);
85  connect(ComboType, SIGNAL(activated(int)), SLOT(slotTypeChanged(int)));
86 
87  QLabel *Label2 = new QLabel(tr("Filter class:"), this);
88  gbox->addWidget(Label2, 2,0);
89  ComboClass = new QComboBox(this);
90  ComboClass->insertItem(tr("Low pass"));
91  ComboClass->insertItem(tr("High pass"));
92  ComboClass->insertItem(tr("Band pass"));
93  ComboClass->insertItem(tr("Band stop"));
94  gbox->addWidget(ComboClass, 2,1);
95  connect(ComboClass, SIGNAL(activated(int)), SLOT(slotClassChanged(int)));
96 
97  IntVal = new QIntValidator(1, 200, this);
98  DoubleVal = new QDoubleValidator(this);
99 
100  LabelOrder = new QLabel(tr("Order:"), this);
101  gbox->addWidget(LabelOrder, 3,0);
102  EditOrder = new QLineEdit("3", this);
103  EditOrder->setValidator(IntVal);
104  gbox->addWidget(EditOrder, 3,1);
105 
106  LabelStart = new QLabel(tr("Corner frequency:"), this);
107  gbox->addWidget(LabelStart, 4,0);
108  EditCorner = new QLineEdit("1", this);
109  EditCorner->setValidator(DoubleVal);
110  gbox->addWidget(EditCorner, 4,1);
111  ComboCorner = new QComboBox(this);
112  ComboCorner->insertItem("Hz");
113  ComboCorner->insertItem("kHz");
114  ComboCorner->insertItem("MHz");
115  ComboCorner->insertItem("GHz");
116  ComboCorner->setCurrentItem(3);
117  gbox->addWidget(ComboCorner, 4,2);
118 
119  LabelStop = new QLabel(tr("Stop frequency:"), this);
120  gbox->addWidget(LabelStop, 5,0);
121  EditStop = new QLineEdit("2", this);
122  EditStop->setValidator(DoubleVal);
123  gbox->addWidget(EditStop, 5,1);
124  ComboStop = new QComboBox(this);
125  ComboStop->insertItem("Hz");
126  ComboStop->insertItem("kHz");
127  ComboStop->insertItem("MHz");
128  ComboStop->insertItem("GHz");
129  ComboStop->setCurrentItem(3);
130  gbox->addWidget(ComboStop, 5,2);
131 
132  LabelBandStop = new QLabel(tr("Stop band frequency:"), this);
133  gbox->addWidget(LabelBandStop, 6,0);
134  EditBandStop = new QLineEdit("3", this);
135  EditBandStop->setValidator(DoubleVal);
136  gbox->addWidget(EditBandStop, 6,1);
137  ComboBandStop = new QComboBox(this);
138  ComboBandStop->insertItem("Hz");
139  ComboBandStop->insertItem("kHz");
140  ComboBandStop->insertItem("MHz");
141  ComboBandStop->insertItem("GHz");
142  ComboBandStop->setCurrentItem(3);
143  gbox->addWidget(ComboBandStop, 6,2);
144 
145  LabelRipple = new QLabel(tr("Pass band ripple:"), this);
146  gbox->addWidget(LabelRipple, 7,0);
147  EditRipple = new QLineEdit("1", this);
148  EditRipple->setValidator(DoubleVal);
149  gbox->addWidget(EditRipple, 7,1);
150  LabelRipple_dB = new QLabel("dB", this);
151  gbox->addWidget(LabelRipple_dB, 7,2);
152 
153  LabelAtten = new QLabel(tr("Stop band attenuation:"), this);
154  gbox->addWidget(LabelAtten, 8,0);
155  EditAtten = new QLineEdit("20", this);
156  EditAtten->setValidator(DoubleVal);
157  gbox->addWidget(EditAtten, 8,1);
158  LabelAtten_dB = new QLabel("dB", this);
159  gbox->addWidget(LabelAtten_dB, 8,2);
160 
161  QLabel *Label9 = new QLabel(tr("Impedance:"), this);
162  gbox->addWidget(Label9, 9,0);
163  EditImpedance = new QLineEdit("50", this);
164  EditImpedance->setValidator(DoubleVal);
165  gbox->addWidget(EditImpedance, 9,1);
166  QLabel *Label10 = new QLabel("Ohm", this);
167  gbox->addWidget(Label10, 9,2);
168 
169 
170  QPushButton *ButtonGo =
171  new QPushButton(tr("Calculate and put into Clipboard"), this);
172  connect(ButtonGo, SIGNAL(clicked()), SLOT(slotCalculate()));
173  gbox->addMultiCellWidget(ButtonGo, 10,10,0,2);
174 
175  LabelResult = new QLabel(this);
176  ResultState = 100;
177  slotShowResult();
178  LabelResult->setAlignment(Qt::AlignHCenter);
179  gbox->addMultiCellWidget(LabelResult, 11,11,0,2);
180 
181 
182  // ------- finally set initial state --------
183  slotTypeChanged(0);
184  slotClassChanged(0);
185 }
186 
188 {
189  delete gbox;
190  delete IntVal;
191  delete DoubleVal;
192 }
193 
194 // ************************************************************
195 void QucsFilter::slotQuit()
196 {
197  int tmp;
198  tmp = x(); // call size and position function in order to ...
199  tmp = y(); // ... set them correctly before closing the ...
200  tmp = width(); // dialog !!! Otherwise the frame of the window ...
201  tmp = height(); // ... will not be recognized (a X11 problem).
202 
203  accept();
204 }
205 
206 // ************************************************************
207 void QucsFilter::slotHelpAbout()
208 {
209  QMessageBox::about(this, tr("About..."),
210  "QucsFilter Version " PACKAGE_VERSION+
211  tr("\nFilter synthesis program\n")+
212  tr("Copyright (C) 2005, 2006 by")+
213  "\nVincent Habchi, Toyoyuki Ishikawa,\n"
214  "Michael Margraf, Stefan Jahn\n"
215  "\nThis is free software; see the source for copying conditions."
216  "\nThere is NO warranty; not even for MERCHANTABILITY or "
217  "\nFITNESS FOR A PARTICULAR PURPOSE.\n\n");
218 }
219 
220 // ************************************************************
221 void QucsFilter::slotHelpAboutQt()
222 {
223  QMessageBox::aboutQt(this, tr("About Qt"));
224 }
225 
226 // ************************************************************
227 void QucsFilter::slotHelpIntro()
228 {
229  HelpDialog *d = new HelpDialog(this);
230  d->show();
231 }
232 
233 // ************************************************************
234 void QucsFilter::setError(const QString& Message)
235 {
236  LabelResult->setText(tr("Result:") + "<font color=\"#FF0000\"><b> " +
237  tr("Error") + "</b></font>");
238  QMessageBox::critical(this, tr("Error"), Message);
239 }
240 
241 // ************************************************************
242 QString * QucsFilter::calculateFilter(struct tFilter * Filter)
243 {
244  QString * s = NULL;
245 
246  if (Filter->Type == TYPE_CAUER) {
247  qf_cauer * F = NULL;
248  double amin, amax, fc, fs, bw, r;
249  fc = Filter->Frequency;
250  amin = Filter->Ripple;
251  fs = Filter->Frequency3;
252  r = Filter->Impedance;
253  amax = Filter->Attenuation;
254  bw = Filter->Frequency2 - fc;
255 
256  switch (Filter->Class) {
257  case CLASS_LOWPASS:
258  F = new qf_cauer (amin, amax, fc, fs, r, 0, LOWPASS);
259  break;
260  case CLASS_HIGHPASS:
261  F = new qf_cauer (amin, amax, fc, fs, r, 0, HIGHPASS);
262  break;
263  case CLASS_BANDPASS:
264  F = new qf_cauer (amin, amax, fc + bw / 2, fs, r, bw, BANDPASS);
265  break;
266  case CLASS_BANDSTOP:
267  F = new qf_cauer (amin, amax, fc + bw / 2, fs, r, bw, BANDSTOP);
268  break;
269  }
270  if (F) {
271  //F->dump();
272  EditOrder->setText(QString::number(F->order()));
273  s = new QString(F->to_qucs().c_str());
274  delete F;
275  }
276  else {
277  s = NULL;
278  }
279  }
280  else {
281  s = LC_Filter::createSchematic(Filter);
282  }
283  return s;
284 }
285 
286 // ************************************************************
287 void QucsFilter::slotCalculate()
288 {
289  // get numerical values from input widgets
290  double CornerFreq = EditCorner->text().toDouble();
291  double StopFreq = EditStop->text().toDouble();
292  double BandStopFreq = EditBandStop->text().toDouble();
293 
294  // add exponent
295  CornerFreq *= pow(10, double(3*ComboCorner->currentItem()));
296  StopFreq *= pow(10, double(3*ComboStop->currentItem()));
297  BandStopFreq *= pow(10, double(3*ComboBandStop->currentItem()));
298 
299  tFilter Filter;
300  Filter.Type = ComboType->currentItem();
301  Filter.Class = ComboClass->currentItem();
302  Filter.Order = EditOrder->text().toInt();
303  Filter.Ripple = EditRipple->text().toDouble();
304  Filter.Attenuation = EditAtten->text().toDouble();
305  Filter.Impedance = EditImpedance->text().toDouble();
306  Filter.Frequency = CornerFreq;
307  Filter.Frequency2 = StopFreq;
308  Filter.Frequency3 = BandStopFreq;
309 
310  if(EditStop->isEnabled())
311  if(Filter.Frequency >= Filter.Frequency2) {
312  setError(tr("Stop frequency must be greater than start frequency."));
313  return;
314  }
315 
316  if(EditOrder->isEnabled()) {
317  if (Filter.Order < 2) {
318  setError(tr("Filter order must not be less than two."));
319  return;
320  }
321  if(Filter.Order > 19) if(Filter.Type == TYPE_BESSEL) {
322  setError(tr("Bessel filter order must not be greater than 19."));
323  return;
324  }
325  }
326 
327  QString * s = calculateFilter(&Filter);
328  if(!s) return;
329 
330  // put resulting filter schematic into clipboard
331  QClipboard *cb = QApplication::clipboard();
332  cb->setText(*s);
333  delete s;
334 
335  // show result for some time
336  ResultState = 0;
337  LabelResult->setText(tr("Result:") + "<font color=\"#008000\"><b> " +
338  tr("Successful") + "</b></font>");
339  QTimer::singleShot(500, this, SLOT(slotShowResult()));
340 }
341 
342 // ************************************************************
343 void QucsFilter::slotShowResult()
344 {
345  if(ResultState > 5) {
346  LabelResult->setText(tr("Result: --"));
347  return;
348  }
349 
350 
351  int c;
352  ResultState++;
353  if(ResultState & 1) c = 0xFF;
354  else c = 0x80;
355  QString s = QString("<font color=\"#00%100\"><b> ").arg(c, 2, 16);
356  LabelResult->setText(tr("Result:") + s + tr("Successful") + "</b></font>");
357 
358  c = 500;
359  if(ResultState > 5) c = 3000;
360  QTimer::singleShot(c, this, SLOT(slotShowResult()));
361 }
362 
363 // ************************************************************
364 void QucsFilter::slotTypeChanged(int index)
365 {
366  switch(index) {
367  case TYPE_BESSEL:
368  case TYPE_BUTTERWORTH:
369  LabelRipple->setEnabled(false);
370  EditRipple->setEnabled(false);
371  LabelRipple_dB->setEnabled(false);
372  break;
373  case TYPE_CHEBYSHEV:
374  case TYPE_CAUER:
375  LabelRipple->setEnabled(true);
376  EditRipple->setEnabled(true);
377  LabelRipple_dB->setEnabled(true);
378  break;
379  }
380  if (index == TYPE_CAUER) {
381  LabelOrder->setEnabled(false);
382  EditOrder->setEnabled(false);
383  LabelAtten->setEnabled(true);
384  EditAtten->setEnabled(true);
385  LabelAtten_dB->setEnabled(true);
386  LabelBandStop->setEnabled(true);
387  EditBandStop->setEnabled(true);
388  ComboBandStop->setEnabled(true);
389  }
390  else {
391  LabelOrder->setEnabled(true);
392  EditOrder->setEnabled(true);
393  LabelAtten->setEnabled(false);
394  EditAtten->setEnabled(false);
395  LabelAtten_dB->setEnabled(false);
396  LabelBandStop->setEnabled(false);
397  EditBandStop->setEnabled(false);
398  ComboBandStop->setEnabled(false);
399  }
400 }
401 
402 // ************************************************************
403 void QucsFilter::slotClassChanged(int index)
404 {
405  switch(index) {
406  case CLASS_LOWPASS:
407  case CLASS_HIGHPASS:
408  LabelStop->setEnabled(false);
409  EditStop->setEnabled(false);
410  ComboStop->setEnabled(false);
411  LabelStart->setText(tr("Corner frequency:"));
412  break;
413  case CLASS_BANDPASS:
414  case CLASS_BANDSTOP:
415  LabelStop->setEnabled(true);
416  EditStop->setEnabled(true);
417  ComboStop->setEnabled(true);
418  LabelStart->setText(tr("Start frequency:"));
419  break;
420  }
421  if (index == CLASS_BANDPASS) {
422  LabelBandStop->setText(tr("Stop band frequency:"));
423  LabelRipple->setText(tr("Pass band ripple:"));
424  }
425  else if (index == CLASS_BANDSTOP) {
426  LabelBandStop->setText(tr("Pass band frequency:"));
427  LabelRipple->setText(tr("Pass band attenuation:"));
428  }
429 }