From 721db2567f7b51c81cbe3769f5a52607c31043c8 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 10 Apr 2014 19:37:44 +0400 Subject: [PATCH 01/90] First commit. Main window interface implemented --- .gitignore | 8 +++++ QFilterSintez.pro | 18 +++++++++++ filtersintez.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++ filtersintez.h | 47 ++++++++++++++++++++++++++++ main.cpp | 11 +++++++ 5 files changed, 163 insertions(+) create mode 100644 .gitignore create mode 100644 QFilterSintez.pro create mode 100644 filtersintez.cpp create mode 100644 filtersintez.h create mode 100644 main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..fb05f14d2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.o +*.cpp~ +*.h~ +QFilterSintez +*.pro.user +Makefile +moc_*.cpp + diff --git a/QFilterSintez.pro b/QFilterSintez.pro new file mode 100644 index 0000000000..ae01c1188b --- /dev/null +++ b/QFilterSintez.pro @@ -0,0 +1,18 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-04-10T18:36:21 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = QFilterSintez +TEMPLATE = app + + +SOURCES += main.cpp\ + filtersintez.cpp + +HEADERS += filtersintez.h diff --git a/filtersintez.cpp b/filtersintez.cpp new file mode 100644 index 0000000000..cc900e49fe --- /dev/null +++ b/filtersintez.cpp @@ -0,0 +1,79 @@ +#include "filtersintez.h" +#include + +FilterSintez::FilterSintez(QWidget *parent) + : QMainWindow(parent) +{ + QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); + + lblInputData = new QLabel(tr("Входные данные")); + lblA1 = new QLabel(tr("Затухание фильтра в полосе пропускания, A1")); + lblA2 = new QLabel(tr("Затухание фильтра в полосе задерживания, A2")); + lblF1 = new QLabel(tr("Частота среза фильтра в полосе пропускания, F1")); + lblF2 = new QLabel(tr("Частота фильтра в полосе задерживания, F2")); + + edtA1 = new QLineEdit; + QDoubleValidator *val1 = new QDoubleValidator(0,100000,3); + edtA1->setValidator(val1); + edtA2 = new QLineEdit; + edtA2->setValidator(val1); + edtF1 = new QLineEdit; + edtF1->setValidator(val1); + edtF2 = new QLineEdit; + edtF2->setValidator(val1); + + + lblTyp = new QLabel(tr("Рассчитать фильтр:")); + btnChebyshev = new QPushButton(tr("Фильтр Чебышева")); + btnButterworth = new QPushButton(tr("Фильтр Баттерворта")); + btnInvChebyshev = new QPushButton(tr("Инверсный фильтр Чебышева")); + btnElliptic = new QPushButton(tr("Эллиптический фильтр")); + + lblResult = new QLabel(tr("Результаты расчёта: ")); + txtResult = new QTextEdit; + + btnHighPass = new QRadioButton(tr("ФВЧ")); + btnLowPass = new QRadioButton(tr("ФНЧ")); + QButtonGroup *grp1 = new QButtonGroup; + grp1->addButton(btnHighPass); + grp1->addButton(btnLowPass); + + top = new QHBoxLayout; + left = new QVBoxLayout; + center = new QVBoxLayout; + right = new QVBoxLayout; + + left->addWidget(lblInputData); + left->addWidget(lblA1); + left->addWidget(edtA1); + left->addWidget(lblA2); + left->addWidget(edtA2); + left->addWidget(lblF1); + left->addWidget(edtF1); + left->addWidget(lblF2); + left->addWidget(edtF2); + left->addWidget(lblTyp); + left->addWidget(btnChebyshev); + left->addWidget(btnButterworth); + left->addWidget(btnInvChebyshev); + left->addWidget(btnElliptic); + + center->addWidget(lblResult); + center->addWidget(txtResult); + + right->addWidget(btnLowPass); + right->addWidget(btnHighPass); + + top->addLayout(left); + top->addLayout(center); + top->addLayout(right); + + zenter = new QWidget; + this->setCentralWidget(zenter); + zenter->setLayout(top); +} + +FilterSintez::~FilterSintez() +{ + +} diff --git a/filtersintez.h b/filtersintez.h new file mode 100644 index 0000000000..2b47eb7cbd --- /dev/null +++ b/filtersintez.h @@ -0,0 +1,47 @@ +#ifndef FILTERSINTEZ_H +#define FILTERSINTEZ_H + +#include +#include + +class FilterSintez : public QMainWindow +{ + Q_OBJECT + +private: + QLabel *lblInputData; + QLabel *lblA1; + QLabel *lblA2; + QLabel *lblF1; + QLabel *lblF2; + QLabel *lblTyp; + + QLineEdit *edtA1; // passband attenuation A1 + QLineEdit *edtA2; // stopband attenuation A2 + QLineEdit *edtF1; // passband cutoff frequency F1 + QLineEdit *edtF2; // stopband cutoff frequency F2 + + QPushButton *btnChebyshev; + QPushButton *btnButterworth; + QPushButton *btnInvChebyshev; + QPushButton *btnElliptic; + + QLabel *lblResult; + QTextEdit *txtResult; + + QRadioButton *btnLowPass; + QRadioButton *btnHighPass; + + QHBoxLayout *top; + QVBoxLayout *left; + QVBoxLayout *center; + QVBoxLayout *right; + + QWidget *zenter; + +public: + FilterSintez(QWidget *parent = 0); + ~FilterSintez(); +}; + +#endif // FILTERSINTEZ_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000000..d26784a60a --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include +#include "filtersintez.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + FilterSintez w; + w.show(); + + return a.exec(); +} From 52189c7d101114e80225cd851013b4b86f4da53c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 11 Apr 2014 15:54:51 +0400 Subject: [PATCH 02/90] Interface with combo boxes --- README | 2 ++ filtersintez.cpp | 64 +++++++++++++++++++++++++++++++++++++++--------- filtersintez.h | 25 ++++++++++++++++--- 3 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000000..938f3f668f --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +QFilterSintez is tool for sintezing active and passive analog filters. + diff --git a/filtersintez.cpp b/filtersintez.cpp index cc900e49fe..001ba45a8b 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -22,22 +22,40 @@ FilterSintez::FilterSintez(QWidget *parent) edtF2 = new QLineEdit; edtF2->setValidator(val1); - lblTyp = new QLabel(tr("Рассчитать фильтр:")); - btnChebyshev = new QPushButton(tr("Фильтр Чебышева")); - btnButterworth = new QPushButton(tr("Фильтр Баттерворта")); - btnInvChebyshev = new QPushButton(tr("Инверсный фильтр Чебышева")); - btnElliptic = new QPushButton(tr("Эллиптический фильтр")); + cbxFilterFunc = new QComboBox; + QStringList lst2; + lst2<addItems(lst2); + btnCalcFiltFunc = new QPushButton(tr("Рассчитать функцию фильтра")); lblResult = new QLabel(tr("Результаты расчёта: ")); txtResult = new QTextEdit; + + lblSch = new QLabel(tr("Схеманая реализация фильтра")); btnHighPass = new QRadioButton(tr("ФВЧ")); btnLowPass = new QRadioButton(tr("ФНЧ")); QButtonGroup *grp1 = new QButtonGroup; grp1->addButton(btnHighPass); grp1->addButton(btnLowPass); + cbxFilterType = new QComboBox; + QStringList lst; + lst<addItems(lst); + + sch_pic = new QLabel; + QPixmap pix("dblquad.png"); + sch_pic->resize(pix.size()); + sch_pic->setPixmap(pix); + top = new QHBoxLayout; left = new QVBoxLayout; center = new QVBoxLayout; @@ -53,16 +71,19 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(lblF2); left->addWidget(edtF2); left->addWidget(lblTyp); - left->addWidget(btnChebyshev); - left->addWidget(btnButterworth); - left->addWidget(btnInvChebyshev); - left->addWidget(btnElliptic); + left->addWidget(cbxFilterFunc); + center->addWidget(lblResult); center->addWidget(txtResult); - right->addWidget(btnLowPass); - right->addWidget(btnHighPass); + left->addWidget(lblSch); + left->addWidget(btnLowPass); + left->addWidget(btnHighPass); + left->addWidget(cbxFilterType); + left->addWidget(btnCalcFiltFunc); + + right->addWidget(sch_pic); top->addLayout(left); top->addLayout(center); @@ -77,3 +98,24 @@ FilterSintez::~FilterSintez() { } + + +void FilterSintez::slotCalcFilter() +{ + +} + +void FilterSintez::calcChebyshev() +{ + +} + +void FilterSintez::calcButterworth() +{ + +} + +void FilterSintez::calcElliptic() +{ + +} diff --git a/filtersintez.h b/filtersintez.h index 2b47eb7cbd..7bdd911495 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -21,24 +21,41 @@ class FilterSintez : public QMainWindow QLineEdit *edtF1; // passband cutoff frequency F1 QLineEdit *edtF2; // stopband cutoff frequency F2 - QPushButton *btnChebyshev; - QPushButton *btnButterworth; - QPushButton *btnInvChebyshev; - QPushButton *btnElliptic; + QComboBox *cbxFilterFunc; + QPushButton *btnCalcFiltFunc; QLabel *lblResult; QTextEdit *txtResult; + QLabel *lblSch; + QRadioButton *btnLowPass; QRadioButton *btnHighPass; + QComboBox *cbxFilterType; + + QPushButton *btnElements; + //QPushButton *btnPassive; + QHBoxLayout *top; QVBoxLayout *left; QVBoxLayout *center; QVBoxLayout *right; + QLabel *sch_pic; + QWidget *zenter; + void calcChebyshev(); + void calcButterworth(); + void calcInvChebyshev(); + void calcElliptic(); + + +private slots: + + void slotCalcFilter(); + public: FilterSintez(QWidget *parent = 0); ~FilterSintez(); From 69af035212ee378d10bbd05569cf8b4ab59ecdbb Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 12 Apr 2014 17:04:34 +0400 Subject: [PATCH 03/90] Implementer filter functions calculation --- Images/dblquad.png | Bin 0 -> 3205 bytes Images/high-pass1.png | Bin 0 -> 1497 bytes Images/low-pass1.png | Bin 0 -> 2268 bytes Images/multiloop.png | Bin 0 -> 1674 bytes Images/noteven.png | Bin 0 -> 3026 bytes Images/passive.png | Bin 0 -> 4782 bytes filtersintez.cpp | 198 ++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 Images/dblquad.png create mode 100644 Images/high-pass1.png create mode 100644 Images/low-pass1.png create mode 100644 Images/multiloop.png create mode 100644 Images/noteven.png create mode 100644 Images/passive.png diff --git a/Images/dblquad.png b/Images/dblquad.png new file mode 100644 index 0000000000000000000000000000000000000000..741eefc815d9c5c467cf52788ce6e5f80780703c GIT binary patch literal 3205 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 w|A)cb*V)}Q95f&mC+XN`3qXxk_J4Oe*Ld;kCd literal 0 HcmV?d00001 diff --git a/Images/high-pass1.png b/Images/high-pass1.png new file mode 100644 index 0000000000000000000000000000000000000000..1b45457f7fd1e199d61a8209d10870e7720586c0 GIT binary patch literal 1497 zcmbtUZ8(z)7=9Uxd5!Y*#vD>4TIU_}HFC@h%SAIEk*RH_OkqB9N}M*?t1>C&93+QM z`jDKYBv&0{K1O0mlw2VaI-wGh)>)@t=lA*XJoj_o_jOlK^l427qZ60FVj+z=&Vc5a^~fR5^Y=UclGvyskzi)8zYxCj$Vs<=dzf*kVnT zRlPJXa`3^ywxXd_-r{Gl9(&;^Ve)j3DjRyV9g7{zgLS#h)m`uGVG z6X|D4U#&PXk6mQNTB7|zbB!{`@f9nHGm$io3d(x7?!*gILj#ueqV}CTVt1O`8AvG9 zm$eBJIH%^zEsMpG!w!*9k+N=(4X&b?+R-pqY*CM&uaUfeY> z4vS^4F-P4oB(njTQ+{A-!c$>yW)S z?_Sj5a)DcNe014Mv6ixEzf!f{v(pq#am(2fCEM@4?|GrP>G}EElkw?3Y!=gEfNApH z75xtKX_3^kCmzq6q=~z^S5@Pi8Fk`|Mc?BSA20bj*>y+Vpuz+bPAMS>$OUpUUz_sk}Jl8==n6$et!I!1DJl?HHu9MRqIk3~ zGkw<(w!pzrxZ*fx1>PFdG1OF#grLgYes?3u18$N%Sn*T@#iMpZD9o&gFl1%d42AO4 z5l+8Eux~;L6)WI<1Z4Zx3{|A<=>dozDT&J&?fv?YVE&2g1ZoPgU`0W;0XW=|QN#D9 zk~lJbW`44{Qp z0j*S1LqidF((2NQ^Rn20A3f(iB{qCE+=vxSKy7#3X#tN%|RE`iJ2b4VG0?eGK` gZ|4|n2a_BeNJRL1VBJSIFJ%CrQ3JfHJz1Im05V~78UO$Q literal 0 HcmV?d00001 diff --git a/Images/low-pass1.png b/Images/low-pass1.png new file mode 100644 index 0000000000000000000000000000000000000000..157e22ee6c81b1ba7d1c4ecccde4c416bb7ec5a6 GIT binary patch literal 2268 zcmcJQdpy(s9>>4JqPgTUEf$J~+`e;NL*k&8(Fmc7jk(P&+guMaGyN!5ZfR7gKpXXoiOuXw6*&V7o005B1 z9(8aB05M(Ry;n-O0S=z_4B;UWZ0BMJ01YhY52B<{i&5Q=*aP)k#GFuQ1{`&F0f0m# z0Hme^z;|IObrt|(KmeF0005>40Ct@#X?L?0Hn#aYA8`OSFR%t53zhV_qdrsskn7o6 zVg>qgY5=f(6zgE;5kJ0Iaw_&uaHm7qW=%ggNKRUQuR+y!PcO}%^ve^YF{hT`0feuD zT^{`K)c1;Lwbb%AsT6UEv`F!O*_~4DvbvUsHD@hK-vac~|Djf z$?6Ej_gp+r@og>=YB5edHI@B*7BPl_`V9`4WfTwRSV6Ym=XPm9r!ggKZ~2{tKJf|7 zJh59g2hok5F9isy&9L_;{?fA#B?^dZnHs%kh7J@bHFL^*R8y(%16OS?y6M;Y1=hFI ziHQf91-#J(K`JilN!ha3@6}X~{MyCj)uF0J)j^Sv)sfWcCxbPvrPKQ-sQBpIT1eBp z1i4GPOK;0!TG@xtm&PaUOVM!9Z`J!?7+wf7FrOJ73&?QzWY8S%UPXtP5x3A zll*>tXRZ#S+x>}3e>L+Y`gq5txs)`r2`#(LA7O0?U1rZwW*J!n4=v+=7-z<&o_ywJ z5(R5`yR*#Bv{Sd2Lv6a;fA_3zbm_n?yJBeZ18if7bB5*bX{)2d*#>emSr)r2qVrNV zi`AHmy|cmnv%O)S8bg{;5qYf z^J`z2cXEPr&Z?&~t-m!EFwSVwjDq4GNA6{HRA-I3w(4*5C+$ce`E^e+vZ#)Slk%0@ zhuqun!?w>u%J%&%Y*F=)PyHJ-#Q0#c$sZt9tl2Mi)K9 zYgY9Pu=eYCp($>v^YN-RJ)kk}5<}alpm@FmNQ!AkK=cg+t z^`H3cNt(7#$f=x*jOc;O%v-c1ly%=8)G^|%MUJj~16VXZ%2vz&Wv!~wLEt%dEIBj@7 z$Ac_VP9y(p{RHYV^wLFkI1Y7^fQPU?P@u~e78(b_m7L%R*I?sVv|bmhhXZ4QzA5s1KW@L7_s7CF@4|R+ZLk~{j_awHvX{Y+icDe4IkW}_yK%%T%j7+ zs9T4(5Yy-W@yc&^kIPE(gV(3Cw+eK(?DfeJ<6{R;YMqLJ6Km&M^JsB&ZUKrtn$fb1 z(67h!7}#6_#bRY{TrHZqpn%N0uAfJ$aNq{b^lM+!yV5k)W`Yem_R+IlaFuxTA>PSw z<`)>Q_yV@1Mg#>$s3W86o$il=U7gJdMLlh*W8`j#X`&L&laAWlWz73}a>xS)Utaaq zJ#pJmIW#V%iL1eRnqnQb(eNm!jBUm2b9`iYjo3KHvSK&Gs??5pw8Sx{H$V5fkZRQ69O`+SIw@j^pRsMDSO%!DA#3h z;=iM>>fGd=xL8F1OUi!|3|d-w{s-VPcS9=L>ZZJuI0W>QWOlN7!D&}<#<23Db!*F8 z@;i-h>G!Z*H=<_a<|8&~3z`lif8zsn_vu(UZMENmKc3oB0ox`l<5 zRuN$-8i=s8y+v5qd*GMvb^HTxy@x!5-A?^R=FS;c8l8u7iMJQrn@E3QSr_;DJS~3! znGGA9G0JaPe$2$&qUz7LeLfEr#L}C@Qk?%iocXOi=UJLh&qQAY@WQFTpXTUIBN1tV zm;g$k@BmCel$jxDW{5(0piD7lrWnvfA2h>&AhXi@!G8oIqDY}Z3BmwqVu%6_O-wvc cXbj2>V~YM2Xt_GpDhvQvM^}e>dqUd30Mi2cIsgCw literal 0 HcmV?d00001 diff --git a/Images/multiloop.png b/Images/multiloop.png new file mode 100644 index 0000000000000000000000000000000000000000..5988f88073f1a121918634deaa43e677c03938f6 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/filtersintez.cpp b/filtersintez.cpp index 001ba45a8b..1cb6c2b6b0 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -1,6 +1,8 @@ #include "filtersintez.h" #include +const double PI=3.141592654; + FilterSintez::FilterSintez(QWidget *parent) : QMainWindow(parent) { @@ -12,14 +14,14 @@ FilterSintez::FilterSintez(QWidget *parent) lblF1 = new QLabel(tr("Частота среза фильтра в полосе пропускания, F1")); lblF2 = new QLabel(tr("Частота фильтра в полосе задерживания, F2")); - edtA1 = new QLineEdit; + edtA1 = new QLineEdit("3"); QDoubleValidator *val1 = new QDoubleValidator(0,100000,3); edtA1->setValidator(val1); - edtA2 = new QLineEdit; + edtA2 = new QLineEdit("20"); edtA2->setValidator(val1); - edtF1 = new QLineEdit; + edtF1 = new QLineEdit("1000"); edtF1->setValidator(val1); - edtF2 = new QLineEdit; + edtF2 = new QLineEdit("1200"); edtF2->setValidator(val1); lblTyp = new QLabel(tr("Рассчитать фильтр:")); @@ -31,6 +33,7 @@ FilterSintez::FilterSintez(QWidget *parent) <addItems(lst2); btnCalcFiltFunc = new QPushButton(tr("Рассчитать функцию фильтра")); + connect(btnCalcFiltFunc,SIGNAL(clicked()),this,SLOT(slotCalcFilter())); lblResult = new QLabel(tr("Результаты расчёта: ")); txtResult = new QTextEdit; @@ -42,6 +45,7 @@ FilterSintez::FilterSintez(QWidget *parent) QButtonGroup *grp1 = new QButtonGroup; grp1->addButton(btnHighPass); grp1->addButton(btnLowPass); + btnLowPass->setChecked(true); cbxFilterType = new QComboBox; QStringList lst; @@ -52,7 +56,7 @@ FilterSintez::FilterSintez(QWidget *parent) cbxFilterType->addItems(lst); sch_pic = new QLabel; - QPixmap pix("dblquad.png"); + QPixmap pix("Images/dblquad.png"); sch_pic->resize(pix.size()); sch_pic->setPixmap(pix); @@ -102,20 +106,204 @@ FilterSintez::~FilterSintez() void FilterSintez::slotCalcFilter() { + switch (cbxFilterFunc->currentIndex()) { + case 0 : calcButterworth(); + break; + case 1 : calcChebyshev(); + break; + case 2 : calcInvChebyshev(); + break; + case 3 : calcElliptic(); + break; + default: break; + } + //calcButterworth(); } void FilterSintez::calcChebyshev() { + float A1 = edtA1->text().toFloat(); + float A2 = edtA2->text().toFloat(); + float F1 = edtF1->text().toFloat(); + float F2 = edtF2->text().toFloat(); + + float W = F2/F1; + float K4=pow(10,(0.1*A1)); + float K5=pow(10,(0.1*A2)); + float C=pow(((K5-1)/(K4-1)),0.5); + float J4=log(C+pow((C*C-1),0.5))/log(W+pow((W*W-1),0.5)); + int N4=round(J4+1); + + QStringList lst; + + lst<setText(lst.join("\n")); } void FilterSintez::calcButterworth() { + //float R1,l,w,q,Wc,C5,K7; + + float A1 = edtA1->text().toFloat(); + float A2 = edtA2->text().toFloat(); + float F1 = edtF1->text().toFloat(); + float F2 = edtF2->text().toFloat(); + + float W=F1/F2; + float K1 = pow(10,(0.1*A1)); + float K2 = pow(10,(0.1*A2)); + float C1=(K1-1)/(K2-1); + float J2=log10(C1)/(2*log10(W)); + int N2 = round(J2+1); + + QStringList lst; + lst<setText(lst.join("\n")); +} + +void FilterSintez::calcInvChebyshev() +{ + float A1 = edtA1->text().toFloat(); + float A2 = edtA2->text().toFloat(); + float F1 = edtF1->text().toFloat(); + float F2 = edtF2->text().toFloat(); + + float W5=F2/F1; + float K4=pow(10,(0.1*A1)); + float C5=pow((K4-1),0.5); + + float J5 = log(C5+pow((C5*C5-1),0.5))/log(W5+pow((W5*W5-1),0.5)); + int N5 = round(J5+1); + + QStringList lst; + + lst<setText(lst.join("\n")); } void FilterSintez::calcElliptic() { + float A1 = edtA1->text().toFloat(); + float A2 = edtA2->text().toFloat(); + float F1 = edtF1->text().toFloat(); + float F2 = edtF2->text().toFloat(); + + float W5=F2/F1; + float K9=F1/F2; + float K4=pow(10,(0.1*A1)); + float K1=pow((1-K9*K9),0.5); + + float J0=A2+12.16-20*log10(pow((K4-1),0.5)); + float J9=6.08+20*log10((1+pow(K1,0.5))/(1-pow(K1,0.5))); + float J7=J0/J9; + int N7=round(J7+1); + + QStringList lst; + lst<setText(lst.join("\n")); } From 3c124936712c7df9a2a084ec4aa18883e8718e0d Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 13 Apr 2014 15:19:14 +0400 Subject: [PATCH 04/90] Implemented dynamic schematic update --- filtersintez.cpp | 25 ++++++++++++++++++++++++- filtersintez.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 1cb6c2b6b0..17a2045c79 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -39,13 +39,14 @@ FilterSintez::FilterSintez(QWidget *parent) txtResult = new QTextEdit; - lblSch = new QLabel(tr("Схеманая реализация фильтра")); + lblSch = new QLabel(tr("Схемная реализация фильтра")); btnHighPass = new QRadioButton(tr("ФВЧ")); btnLowPass = new QRadioButton(tr("ФНЧ")); QButtonGroup *grp1 = new QButtonGroup; grp1->addButton(btnHighPass); grp1->addButton(btnLowPass); btnLowPass->setChecked(true); + connect(grp1,SIGNAL(buttonClicked(int)),this,SLOT(slotUpdateSchematic())); cbxFilterType = new QComboBox; QStringList lst; @@ -54,6 +55,7 @@ FilterSintez::FilterSintez(QWidget *parent) <addItems(lst); + connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); sch_pic = new QLabel; QPixmap pix("Images/dblquad.png"); @@ -121,6 +123,27 @@ void FilterSintez::slotCalcFilter() //calcButterworth(); } +void FilterSintez::slotUpdateSchematic() +{ + QString s; + switch (cbxFilterType->currentIndex()) { + case 0 : s = "Images/dblquad.png"; + break; + case 1 : s= "Images/multiloop.png"; + break; + case 2 : if (btnHighPass->isChecked()) s = "Images/high-pass1.png"; + else s = "Images/low-pass1.png"; + break; + case 3 : s = "Images/passive.png"; + break; + default: break; + } + + QPixmap pix(s); + sch_pic->resize(pix.size()); + sch_pic->setPixmap(pix); +} + void FilterSintez::calcChebyshev() { float A1 = edtA1->text().toFloat(); diff --git a/filtersintez.h b/filtersintez.h index 7bdd911495..f34e4c8612 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -55,6 +55,7 @@ class FilterSintez : public QMainWindow private slots: void slotCalcFilter(); + void slotUpdateSchematic(); public: FilterSintez(QWidget *parent = 0); From 46bb5c8b581bc041d504669da0891f9f18a981a2 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 14 Apr 2014 16:59:44 +0400 Subject: [PATCH 05/90] Added stubs for filer schematic calculation --- filtersintez.cpp | 35 +++++++++++++++++++++++++++++++++++ filtersintez.h | 9 +++++++++ 2 files changed, 44 insertions(+) diff --git a/filtersintez.cpp b/filtersintez.cpp index 17a2045c79..cc247e59b4 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -330,3 +330,38 @@ void FilterSintez::calcElliptic() txtResult->setText(lst.join("\n")); } + +void FilterSintez::calcDblQuadHPF() +{ + +} + +void FilterSintez::calcDblQuadLPF() +{ + +} + +void FilterSintez::calcMultiloopHPF() +{ + +} + +void FilterSintez::calcMultiloopLPF() +{ + +} + +void FilterSintez::calcSallenKeyHPF() +{ + +} + +void FilterSintez::calcSallenKeyLPF() +{ + +} + +void FilterSintez::calcPassive() +{ + +} diff --git a/filtersintez.h b/filtersintez.h index f34e4c8612..e960552f05 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -51,6 +51,15 @@ class FilterSintez : public QMainWindow void calcInvChebyshev(); void calcElliptic(); + void calcDblQuadLPF(); + void calcDblQuadHPF(); + void calcMultiloopLPF(); + void calcMultiloopHPF(); + void calcSallenKeyLPF(); + void calcSallenKeyHPF(); + void calcPassive(); + + private slots: From 7e28f5e1a762211e2778366f5b5fafaeba4175b6 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 15 Apr 2014 16:30:42 +0400 Subject: [PATCH 06/90] Implemented Sallen-Key low-pass filter calculation --- filtersintez.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++----- filtersintez.h | 13 ++++--- 2 files changed, 90 insertions(+), 13 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index cc247e59b4..b05bcab962 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -6,6 +6,9 @@ const double PI=3.141592654; FilterSintez::FilterSintez(QWidget *parent) : QMainWindow(parent) { + Nfil = 4; + Fc = 1000; + QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); lblInputData = new QLabel(tr("Входные данные")); @@ -13,6 +16,7 @@ FilterSintez::FilterSintez(QWidget *parent) lblA2 = new QLabel(tr("Затухание фильтра в полосе задерживания, A2")); lblF1 = new QLabel(tr("Частота среза фильтра в полосе пропускания, F1")); lblF2 = new QLabel(tr("Частота фильтра в полосе задерживания, F2")); + lblKv = new QLabel(tr("Усиление фильтра, Kv")); edtA1 = new QLineEdit("3"); QDoubleValidator *val1 = new QDoubleValidator(0,100000,3); @@ -23,6 +27,8 @@ FilterSintez::FilterSintez(QWidget *parent) edtF1->setValidator(val1); edtF2 = new QLineEdit("1200"); edtF2->setValidator(val1); + edtKv = new QLineEdit("2"); + edtKv->setValidator(val1); lblTyp = new QLabel(tr("Рассчитать фильтр:")); cbxFilterFunc = new QComboBox; @@ -34,6 +40,8 @@ FilterSintez::FilterSintez(QWidget *parent) cbxFilterFunc->addItems(lst2); btnCalcFiltFunc = new QPushButton(tr("Рассчитать функцию фильтра")); connect(btnCalcFiltFunc,SIGNAL(clicked()),this,SLOT(slotCalcFilter())); + btnCalcSchematic = new QPushButton(tr("Рассчитать элементы схемы фильтра")); + connect(btnCalcSchematic,SIGNAL(clicked()),SLOT(slotCalcSchematic())); lblResult = new QLabel(tr("Результаты расчёта: ")); txtResult = new QTextEdit; @@ -76,6 +84,8 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(edtF1); left->addWidget(lblF2); left->addWidget(edtF2); + left->addWidget(lblKv); + left->addWidget(edtKv); left->addWidget(lblTyp); left->addWidget(cbxFilterFunc); @@ -88,6 +98,7 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(btnHighPass); left->addWidget(cbxFilterType); left->addWidget(btnCalcFiltFunc); + left->addWidget(btnCalcSchematic); right->addWidget(sch_pic); @@ -109,13 +120,13 @@ FilterSintez::~FilterSintez() void FilterSintez::slotCalcFilter() { switch (cbxFilterFunc->currentIndex()) { - case 0 : calcButterworth(); + case 0 : Nfil = calcButterworth(); break; - case 1 : calcChebyshev(); + case 1 : Nfil = calcChebyshev(); break; - case 2 : calcInvChebyshev(); + case 2 : Nfil = calcInvChebyshev(); break; - case 3 : calcElliptic(); + case 3 : Nfil = calcElliptic(); break; default: break; } @@ -123,6 +134,22 @@ void FilterSintez::slotCalcFilter() //calcButterworth(); } +void FilterSintez::slotCalcSchematic() +{ + switch (cbxFilterType->currentIndex()) { + case 0 : calcDblQuadHPF(); + break; + case 1 : calcMultiloopHPF(); + break; + case 2 : if (btnHighPass->isChecked()) calcSallenKeyHPF(); + else calcSallenKeyLPF(); + break; + case 3 : calcPassive(); + break; + default: break; + } +} + void FilterSintez::slotUpdateSchematic() { QString s; @@ -144,12 +171,13 @@ void FilterSintez::slotUpdateSchematic() sch_pic->setPixmap(pix); } -void FilterSintez::calcChebyshev() +int FilterSintez::calcChebyshev() { float A1 = edtA1->text().toFloat(); float A2 = edtA2->text().toFloat(); float F1 = edtF1->text().toFloat(); float F2 = edtF2->text().toFloat(); + Fc = F1; float W = F2/F1; float K4=pow(10,(0.1*A1)); @@ -184,9 +212,10 @@ void FilterSintez::calcChebyshev() } txtResult->setText(lst.join("\n")); + return N4; } -void FilterSintez::calcButterworth() +int FilterSintez::calcButterworth() { //float R1,l,w,q,Wc,C5,K7; @@ -194,6 +223,7 @@ void FilterSintez::calcButterworth() float A2 = edtA2->text().toFloat(); float F1 = edtF1->text().toFloat(); float F2 = edtF2->text().toFloat(); + Fc = F1; float W=F1/F2; float K1 = pow(10,(0.1*A1)); @@ -242,14 +272,17 @@ void FilterSintez::calcButterworth() } txtResult->setText(lst.join("\n")); + + return N2; } -void FilterSintez::calcInvChebyshev() +int FilterSintez::calcInvChebyshev() { float A1 = edtA1->text().toFloat(); float A2 = edtA2->text().toFloat(); float F1 = edtF1->text().toFloat(); float F2 = edtF2->text().toFloat(); + Fc = F1; float W5=F2/F1; float K4=pow(10,(0.1*A1)); @@ -285,14 +318,17 @@ void FilterSintez::calcInvChebyshev() } txtResult->setText(lst.join("\n")); + + return N5; } -void FilterSintez::calcElliptic() +int FilterSintez::calcElliptic() { float A1 = edtA1->text().toFloat(); float A2 = edtA2->text().toFloat(); float F1 = edtF1->text().toFloat(); float F2 = edtF2->text().toFloat(); + Fc = F1; float W5=F2/F1; float K9=F1/F2; @@ -329,6 +365,8 @@ void FilterSintez::calcElliptic() } txtResult->setText(lst.join("\n")); + + return N7; } void FilterSintez::calcDblQuadHPF() @@ -353,12 +391,46 @@ void FilterSintez::calcMultiloopLPF() void FilterSintez::calcSallenKeyHPF() { - + calcSallenKeyLPF(); } void FilterSintez::calcSallenKeyLPF() { + float C1[20],C2[20],R1[20],R2[20],R3[20],R4[20]; + + float Kv = edtKv->text().toFloat(); + + QStringList lst; + lst<<"N C1 C2 R1 R2 R3 R4"; + + for (int K=1; K <= Nfil/2; K++) { + float B = 2*sin((2*K-1)*M_PI/(2*Nfil)); + const float C = 1; + + C2[K] = 10 / Fc; + + float Wc = 2*M_PI*Fc; + C1[K] = (B*B+4*C*(Kv-1))*C2[K]/(4*C); + + R1[K] = 2/(Wc*(B*C2[K]+sqrt((B*B + 4*C*(Kv-1))*(C2[K]*C2[K])-4*C*C1[K]*C2[K]))); + + R2[K] = 1/(C*C1[K]*C2[K]*R1[K]*Wc*Wc); + + if (Kv != 1.0) { + R3[K] = Kv*(R1[K] + R2[K])/(Kv - 1); + R4[K] = Kv*(R1[K] + R2[K]); + } else { + R3[K] = 999; + R4[K] = 0; + } + + lst<setText(lst.join("\n")); } void FilterSintez::calcPassive() diff --git a/filtersintez.h b/filtersintez.h index e960552f05..510ba1c32d 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -15,14 +15,17 @@ class FilterSintez : public QMainWindow QLabel *lblF1; QLabel *lblF2; QLabel *lblTyp; + QLabel *lblKv; QLineEdit *edtA1; // passband attenuation A1 QLineEdit *edtA2; // stopband attenuation A2 QLineEdit *edtF1; // passband cutoff frequency F1 QLineEdit *edtF2; // stopband cutoff frequency F2 + QLineEdit *edtKv; QComboBox *cbxFilterFunc; QPushButton *btnCalcFiltFunc; + QPushButton *btnCalcSchematic; QLabel *lblResult; QTextEdit *txtResult; @@ -46,10 +49,10 @@ class FilterSintez : public QMainWindow QWidget *zenter; - void calcChebyshev(); - void calcButterworth(); - void calcInvChebyshev(); - void calcElliptic(); + int calcChebyshev(); + int calcButterworth(); + int calcInvChebyshev(); + int calcElliptic(); void calcDblQuadLPF(); void calcDblQuadHPF(); @@ -59,12 +62,14 @@ class FilterSintez : public QMainWindow void calcSallenKeyHPF(); void calcPassive(); + float Nfil,Fc; private slots: void slotCalcFilter(); void slotUpdateSchematic(); + void slotCalcSchematic(); public: FilterSintez(QWidget *parent = 0); From 2f02ad2df8b7df428d6028bb6a0d116dd2271566 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 17 Apr 2014 10:54:58 +0400 Subject: [PATCH 07/90] Implemented Sallen-Key high pass filtersintez --- filtersintez.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index b05bcab962..1f436e248f 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -137,9 +137,11 @@ void FilterSintez::slotCalcFilter() void FilterSintez::slotCalcSchematic() { switch (cbxFilterType->currentIndex()) { - case 0 : calcDblQuadHPF(); + case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); + else calcDblQuadLPF(); break; - case 1 : calcMultiloopHPF(); + case 1 : if (btnHighPass->isChecked()) calcMultiloopHPF(); + else calcMultiloopLPF(); break; case 2 : if (btnHighPass->isChecked()) calcSallenKeyHPF(); else calcSallenKeyLPF(); @@ -391,7 +393,48 @@ void FilterSintez::calcMultiloopLPF() void FilterSintez::calcSallenKeyHPF() { - calcSallenKeyLPF(); + + float C1[20],R1[20],R2[20],R3[20],R4[20]; + + float Kv = edtKv->text().toFloat(); + + QStringList lst; + lst<<"N C1(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; + + float Wc = 2*M_PI*Fc; + + for (int K=1; K <= Nfil/2; K++) { + float B = 2*sin((2*K-1)*M_PI/(2*Nfil)); + const float C = 1; + + qDebug()<setText(lst.join("\n")); + } void FilterSintez::calcSallenKeyLPF() @@ -401,12 +444,14 @@ void FilterSintez::calcSallenKeyLPF() float Kv = edtKv->text().toFloat(); QStringList lst; - lst<<"N C1 C2 R1 R2 R3 R4"; + lst<<"N C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; for (int K=1; K <= Nfil/2; K++) { float B = 2*sin((2*K-1)*M_PI/(2*Nfil)); const float C = 1; + qDebug()< Date: Fri, 18 Apr 2014 14:13:42 +0400 Subject: [PATCH 08/90] Corrected bitterworth poles and zeros calculation routine --- filtersintez.cpp | 54 ++++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 1f436e248f..f7cb6af806 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -204,13 +204,12 @@ int FilterSintez::calcChebyshev() float G1=0.5*(exp(V5)-exp(-V5)); float G2=0.5*(exp(V4)+exp(-V4)); - float R0[50],S4[50],O4[50]; - lst<<""<setText(lst.join("\n")); @@ -227,51 +226,30 @@ int FilterSintez::calcButterworth() float F2 = edtF2->text().toFloat(); Fc = F1; - float W=F1/F2; float K1 = pow(10,(0.1*A1)); float K2 = pow(10,(0.1*A2)); float C1=(K1-1)/(K2-1); - float J2=log10(C1)/(2*log10(W)); + float J2=log10(C1)/(2*log10(F1/F2)); int N2 = round(J2+1); QStringList lst; lst<setText(lst.join("\n")); From 732d567e7e1ac42c5809e921da9872ff63b97e21 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 18 Apr 2014 15:51:24 +0400 Subject: [PATCH 09/90] Implemented Chebyshev filter poles calculation --- filtersintez.cpp | 145 +++++++++++++++++++++++++++++------------------ filtersintez.h | 7 +++ 2 files changed, 96 insertions(+), 56 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index f7cb6af806..3e92c93776 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -16,8 +16,11 @@ FilterSintez::FilterSintez(QWidget *parent) lblA2 = new QLabel(tr("Затухание фильтра в полосе задерживания, A2")); lblF1 = new QLabel(tr("Частота среза фильтра в полосе пропускания, F1")); lblF2 = new QLabel(tr("Частота фильтра в полосе задерживания, F2")); + lblRpl1 = new QLabel(tr("амплитуда пульсаций в полосе пропускания (дБ)")); + lblRpl2 = new QLabel(tr("Амплитуда пульсаций в полосе задерживания (дБ)")); lblKv = new QLabel(tr("Усиление фильтра, Kv")); + edtA1 = new QLineEdit("3"); QDoubleValidator *val1 = new QDoubleValidator(0,100000,3); edtA1->setValidator(val1); @@ -27,6 +30,10 @@ FilterSintez::FilterSintez(QWidget *parent) edtF1->setValidator(val1); edtF2 = new QLineEdit("1200"); edtF2->setValidator(val1); + edtPassbRpl = new QLineEdit("3"); + edtPassbRpl->setValidator(val1); + edtStopbRpl = new QLineEdit("3"); + edtStopbRpl->setValidator(val1); edtKv = new QLineEdit("2"); edtKv->setValidator(val1); @@ -84,6 +91,10 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(edtF1); left->addWidget(lblF2); left->addWidget(edtF2); + left->addWidget(lblRpl1); + left->addWidget(edtPassbRpl); + left->addWidget(lblRpl2); + left->addWidget(edtStopbRpl); left->addWidget(lblKv); left->addWidget(edtKv); left->addWidget(lblTyp); @@ -136,6 +147,9 @@ void FilterSintez::slotCalcFilter() void FilterSintez::slotCalcSchematic() { + + slotCalcFilter(); + switch (cbxFilterType->currentIndex()) { case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); else calcDblQuadLPF(); @@ -175,45 +189,52 @@ void FilterSintez::slotUpdateSchematic() int FilterSintez::calcChebyshev() { - float A1 = edtA1->text().toFloat(); + float alpha = edtPassbRpl->text().toFloat(); float A2 = edtA2->text().toFloat(); float F1 = edtF1->text().toFloat(); float F2 = edtF2->text().toFloat(); Fc = F1; - float W = F2/F1; - float K4=pow(10,(0.1*A1)); - float K5=pow(10,(0.1*A2)); - float C=pow(((K5-1)/(K4-1)),0.5); - float J4=log(C+pow((C*C-1),0.5))/log(W+pow((W*W-1),0.5)); - int N4=round(J4+1); + float eps=sqrt(pow(10,0.1*alpha)-1); - QStringList lst; + float N1 = acosh(sqrt((pow(10,0.1*A2)-1)/(eps*eps)))/acosh(F2/F1); + int N = ceil(N1); + QStringList lst; lst<setText(lst.join("\n")); - return N4; + return N; } int FilterSintez::calcButterworth() @@ -243,14 +264,26 @@ int FilterSintez::calcButterworth() lst<<""; lst<setText(lst.join("\n")); return N2; @@ -381,34 +414,34 @@ void FilterSintez::calcSallenKeyHPF() float Wc = 2*M_PI*Fc; - for (int K=1; K <= Nfil/2; K++) { - float B = 2*sin((2*K-1)*M_PI/(2*Nfil)); - const float C = 1; + for (int k=1; k <= Nfil/2; k++) { + float B = coeffB.at(k-1); + float C = coeffC.at(k-1); qDebug()<setText(lst.join("\n")); @@ -424,38 +457,38 @@ void FilterSintez::calcSallenKeyLPF() QStringList lst; lst<<"N C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; - for (int K=1; K <= Nfil/2; K++) { - float B = 2*sin((2*K-1)*M_PI/(2*Nfil)); + for (int k=1; k <= Nfil/2; k++) { + float B = 2*sin((2*k-1)*M_PI/(2*Nfil)); const float C = 1; qDebug()<setText(lst.join("\n")); diff --git a/filtersintez.h b/filtersintez.h index 510ba1c32d..b7df7e6722 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -16,12 +16,16 @@ class FilterSintez : public QMainWindow QLabel *lblF2; QLabel *lblTyp; QLabel *lblKv; + QLabel *lblRpl1; + QLabel *lblRpl2; QLineEdit *edtA1; // passband attenuation A1 QLineEdit *edtA2; // stopband attenuation A2 QLineEdit *edtF1; // passband cutoff frequency F1 QLineEdit *edtF2; // stopband cutoff frequency F2 QLineEdit *edtKv; + QLineEdit *edtPassbRpl; + QLineEdit *edtStopbRpl; QComboBox *cbxFilterFunc; QPushButton *btnCalcFiltFunc; @@ -64,6 +68,9 @@ class FilterSintez : public QMainWindow float Nfil,Fc; + QVector coeffB; + QVector coeffC; + private slots: From 49260827f87e2db6a2b7aecd9a18a744f867af2c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 19 Apr 2014 11:24:25 +0400 Subject: [PATCH 10/90] Implemented poles calculation with std::complex --- filtersintez.cpp | 62 +++++++++++++++++++++--------------------------- filtersintez.h | 3 +++ 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 3e92c93776..481b52751a 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -211,27 +211,18 @@ int FilterSintez::calcChebyshev() float b = cosh((asinh(1/eps))/N); qDebug()< pol(re,im); + Poles.append(pol); + lst<setText(lst.join("\n")); return N; @@ -260,30 +251,24 @@ int FilterSintez::calcButterworth() lst< pol(re,im); + Poles.append(pol); + lst<setText(lst.join("\n")); return N2; @@ -415,8 +400,11 @@ void FilterSintez::calcSallenKeyHPF() float Wc = 2*M_PI*Fc; for (int k=1; k <= Nfil/2; k++) { - float B = coeffB.at(k-1); - float C = coeffC.at(k-1); + + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float B = -2.0*re; + float C = re*re + im*im; qDebug()< #include +#include class FilterSintez : public QMainWindow { @@ -66,6 +67,8 @@ class FilterSintez : public QMainWindow void calcSallenKeyHPF(); void calcPassive(); + QVector< std::complex > Poles; + float Nfil,Fc; QVector coeffB; From a0c27662b7904917a6296ae2acb6b1a2a2b98830 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 19 Apr 2014 16:39:18 +0400 Subject: [PATCH 11/90] Implemented Filter class --- QFilterSintez.pro | 8 +++++-- filter.cpp | 7 ++++++ filter.h | 33 ++++++++++++++++++++++++++++ filtersintez.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++----- filtersintez.h | 3 ++- sallenkey.cpp | 17 ++++++++++++++ sallenkey.h | 31 ++++++++++++++++++++++++++ 7 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 filter.cpp create mode 100644 filter.h create mode 100644 sallenkey.cpp create mode 100644 sallenkey.h diff --git a/QFilterSintez.pro b/QFilterSintez.pro index ae01c1188b..801d710edb 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -13,6 +13,10 @@ TEMPLATE = app SOURCES += main.cpp\ - filtersintez.cpp + filtersintez.cpp \ + filter.cpp \ + sallenkey.cpp -HEADERS += filtersintez.h +HEADERS += filtersintez.h \ + filter.h \ + sallenkey.h diff --git a/filter.cpp b/filter.cpp new file mode 100644 index 0000000000..c59bb3e459 --- /dev/null +++ b/filter.cpp @@ -0,0 +1,7 @@ +#include "filter.h" + +Filter::Filter(QVector< std::complex > poles_, bool HighPass_) +{ + Poles = poles_; + HighPass = HighPass_; +} diff --git a/filter.h b/filter.h new file mode 100644 index 0000000000..e4f575b1c5 --- /dev/null +++ b/filter.h @@ -0,0 +1,33 @@ +#ifndef FILTER_H +#define FILTER_H + +#include +#include +#include + +class Filter +{ + +private: + QVector< std::complex > Poles; + + bool HighPass; + +public: + + + Filter(QVector< std::complex > poles_, bool HighPass_ = false); + + virtual QString* createSchematic() + { + + } + + virtual void calcFilter() + { + + } + +}; + +#endif // FILTER_H diff --git a/filtersintez.cpp b/filtersintez.cpp index 481b52751a..ec780a48be 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -432,6 +432,31 @@ void FilterSintez::calcSallenKeyHPF() " "+QString::number(R4[k]); } + if (Nfil%2 != 0) { + int k = Nfil/2 + 1; + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float C = re*re + im*im; + C1[k] = 10/Fc; + R1[k] = 1.0/(Wc*C*C1[k]); + + if (Kv != 1.0) { + R3[k] = Kv*(R1[k] + R2[k])/(Kv - 1); + R4[k] = Kv*(R1[k] + R2[k]); + } else { + R3[k] = 999; + R4[k] = 0; + } + R1[k]=1000*R1[k]; + R2[k]=1000*R2[k]; + R3[k]=1000*R3[k]; + R4[k]=1000*R4[k]; + + lst<setText(lst.join("\n")); } @@ -441,6 +466,7 @@ void FilterSintez::calcSallenKeyLPF() float C1[20],C2[20],R1[20],R2[20],R3[20],R4[20]; float Kv = edtKv->text().toFloat(); + float Wc = 2*M_PI*Fc; QStringList lst; lst<<"N C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; @@ -456,13 +482,8 @@ void FilterSintez::calcSallenKeyLPF() C2[k] = 10 / Fc; - - float Wc = 2*M_PI*Fc; - C1[k] = (B*B+4*C*(Kv-1))*C2[k]/(4*C); - R1[k] = 2/(Wc*(B*C2[k]+sqrt((B*B + 4*C*(Kv-1))*(C2[k]*C2[k])-4*C*C1[k]*C2[k]))); - R2[k] = 1/(C*C1[k]*C2[k]*R1[k]*Wc*Wc); if (Kv != 1.0) { @@ -483,6 +504,31 @@ void FilterSintez::calcSallenKeyLPF() " "+QString::number(R4[k]); } + if (Nfil%2 != 0) { + int k = Nfil/2 + 1; + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float C = re*re + im*im; + C1[k] = 10/Fc; + R1[k] = 1.0/(Wc*C*C1[k]); + + if (Kv != 1.0) { + R3[k] = Kv*(R1[k] + R2[k])/(Kv - 1); + R4[k] = Kv*(R1[k] + R2[k]); + } else { + R3[k] = 999; + R4[k] = 0; + } + R1[k]=1000*R1[k]; + R2[k]=1000*R2[k]; + R3[k]=1000*R3[k]; + R4[k]=1000*R4[k]; + + lst<setText(lst.join("\n")); } diff --git a/filtersintez.h b/filtersintez.h index e219d1489a..5ae086ae39 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -69,7 +69,8 @@ class FilterSintez : public QMainWindow QVector< std::complex > Poles; - float Nfil,Fc; + float Fc; + int Nfil; QVector coeffB; QVector coeffC; diff --git a/sallenkey.cpp b/sallenkey.cpp new file mode 100644 index 0000000000..b01beeff7f --- /dev/null +++ b/sallenkey.cpp @@ -0,0 +1,17 @@ +#include "sallenkey.h" + +SallenKey::SallenKey(QVector< std::complex > poles_, bool HighPass_) : + Filter(poles_, HighPass_) +{ +} + +QString* SallenKey::createSchematic() +{ + +} + + +void SallenKey::calcFilter() +{ + +} diff --git a/sallenkey.h b/sallenkey.h new file mode 100644 index 0000000000..77b5699cef --- /dev/null +++ b/sallenkey.h @@ -0,0 +1,31 @@ +#ifndef SALLENKEY_H +#define SALLENKEY_H + +#include +#include +#include +#include "filter.h" + +class SallenKey : public Filter +{ + +private: + + std::vector C1; + std::vector C2; + std::vector R1; + std::vector R2; + std::vector R3; + std::vector R4; + + void calcSallenKeyHPF(); + void calcSallenKeyLPF(); + +public: + SallenKey(QVector< std::complex > poles_, bool HighPass_ = false); + + QString* createSchematic(); + void calcFilter(); +}; + +#endif // SALLENKEY_H From 34cf9fd5c6cc8366b62d87c1043bbf832c0fd585 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 20 Apr 2014 14:38:21 +0400 Subject: [PATCH 12/90] Started moving filter schematic sintez fo specific class --- filter.cpp | 12 +++++-- filter.h | 12 +++++-- filtersintez.cpp | 2 +- sallenkey.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++-- sallenkey.h | 18 ++++++---- 5 files changed, 118 insertions(+), 15 deletions(-) diff --git a/filter.cpp b/filter.cpp index c59bb3e459..b4ca0b86b4 100644 --- a/filter.cpp +++ b/filter.cpp @@ -1,7 +1,15 @@ #include "filter.h" -Filter::Filter(QVector< std::complex > poles_, bool HighPass_) +Filter::Filter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) { Poles = poles_; - HighPass = HighPass_; + Nfil = Poles.count(); + ftype = type_; + Fc = Fcutoff; + Kv = Kv_; +} + +Filter::~Filter() +{ + } diff --git a/filter.h b/filter.h index e4f575b1c5..e4774e9972 100644 --- a/filter.h +++ b/filter.h @@ -8,15 +8,21 @@ class Filter { -private: +public: + enum FType {HighPass, LowPass, BandPass}; + +protected: QVector< std::complex > Poles; - bool HighPass; + Filter::FType ftype; + int Nfil; + float Fc,Kv; public: - Filter(QVector< std::complex > poles_, bool HighPass_ = false); + Filter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); + ~Filter(); virtual QString* createSchematic() { diff --git a/filtersintez.cpp b/filtersintez.cpp index ec780a48be..7d95985259 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -465,7 +465,7 @@ void FilterSintez::calcSallenKeyLPF() { float C1[20],C2[20],R1[20],R2[20],R3[20],R4[20]; - float Kv = edtKv->text().toFloat(); + float Kv = 1.0; float Wc = 2*M_PI*Fc; QStringList lst; diff --git a/sallenkey.cpp b/sallenkey.cpp index b01beeff7f..3284819eef 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -1,8 +1,9 @@ #include "sallenkey.h" -SallenKey::SallenKey(QVector< std::complex > poles_, bool HighPass_) : - Filter(poles_, HighPass_) +SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) : + Filter(poles_, type_, Fcutoff, Kv_) { + } QString* SallenKey::createSchematic() @@ -12,6 +13,90 @@ QString* SallenKey::createSchematic() void SallenKey::calcFilter() +{ + switch (ftype) { + case Filter::LowPass : calcSallenKeyLPF(); + break; + case Filter::HighPass : calcSallenKeyHPF(); + break; + default: + break; + } +} + + +void SallenKey::calcSallenKeyLPF() +{ + float R1,R2,R3,R4,C1,C2; + float Wc = 2*M_PI*Fc; + + for (int k=1; k <= Nfil/2; k++) { + + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float B = -2.0*re; + float C = re*re + im*im; + + qDebug()< #include "filter.h" +struct RC_elements { + float R1; + float R2; + float R3; + float R4; + float C1; + float C2; +}; + class SallenKey : public Filter { private: - std::vector C1; - std::vector C2; - std::vector R1; - std::vector R2; - std::vector R3; - std::vector R4; + QVector Stages; void calcSallenKeyHPF(); void calcSallenKeyLPF(); public: - SallenKey(QVector< std::complex > poles_, bool HighPass_ = false); + SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); QString* createSchematic(); void calcFilter(); From b33db0b7ad18653cfc2b48b88f80f0491047711c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 20 Apr 2014 17:00:06 +0400 Subject: [PATCH 13/90] Filter schematic elements calculation methods moved to Filter class completely. Started filter schematic Qucs file generating implementation --- QFilterSintez.pro | 6 +- filter.cpp | 48 +++++++++++++ filter.h | 17 ++++- filtersintez.cpp | 168 ++++++---------------------------------------- mfbfilter.cpp | 16 +++++ mfbfilter.h | 17 +++++ sallenkey.cpp | 80 ++++++++++++++++------ sallenkey.h | 10 --- 8 files changed, 180 insertions(+), 182 deletions(-) create mode 100644 mfbfilter.cpp create mode 100644 mfbfilter.h diff --git a/QFilterSintez.pro b/QFilterSintez.pro index 801d710edb..2c07738826 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -15,8 +15,10 @@ TEMPLATE = app SOURCES += main.cpp\ filtersintez.cpp \ filter.cpp \ - sallenkey.cpp + sallenkey.cpp \ + mfbfilter.cpp HEADERS += filtersintez.h \ filter.h \ - sallenkey.h + sallenkey.h \ + mfbfilter.h diff --git a/filter.cpp b/filter.cpp index b4ca0b86b4..3243f2a8bb 100644 --- a/filter.cpp +++ b/filter.cpp @@ -13,3 +13,51 @@ Filter::~Filter() { } + +void Filter::calcFirstOrder() +{ + if (Nfil%2 != 0) { + + float R2,R3; + + int k = Nfil/2 + 1; + float Wc = 2*M_PI*Fc; + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float C = re*re + im*im; + float C1 = 10/Fc; + float R1 = 1.0/(Wc*C*C1); + + + if (Kv != 1.0) { + R2 = Kv*R1/(Kv - 1); + R3 = Kv*R1; + } else { + R2 = 999; + R3 = 0; + } + RC_elements curr_stage; + curr_stage.N = k; + curr_stage.R1 = 1000*R1; + curr_stage.R2 = 1000*R2; + curr_stage.R3 = 1000*R3; + curr_stage.R4 = 0; + curr_stage.C1 = C1; + curr_stage.C2 = 0; + Stages.append(curr_stage); + + } + +} + +void Filter::createPartList(QStringList &lst) +{ + lst<<"N C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; + RC_elements stage; + + foreach (stage,Stages) { + lst< #include +struct RC_elements { + int N; + float R1; + float R2; + float R3; + float R4; + float C1; + float C2; +}; + class Filter { @@ -13,6 +23,7 @@ class Filter protected: QVector< std::complex > Poles; + QVector Stages; Filter::FType ftype; int Nfil; @@ -22,7 +33,11 @@ class Filter Filter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); - ~Filter(); + virtual ~Filter(); + + void calcFirstOrder(); + + void createPartList(QStringList &lst); virtual QString* createSchematic() { diff --git a/filtersintez.cpp b/filtersintez.cpp index 7d95985259..b9edfa2afd 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -1,7 +1,7 @@ #include "filtersintez.h" +#include "sallenkey.h" #include -const double PI=3.141592654; FilterSintez::FilterSintez(QWidget *parent) : QMainWindow(parent) @@ -150,6 +150,17 @@ void FilterSintez::slotCalcSchematic() slotCalcFilter(); + Filter::FType ftyp; + if (btnHighPass->isChecked()) { + ftyp = Filter::HighPass; + } else { + ftyp = Filter::LowPass; + } + + QStringList lst; + + float Kv = edtKv->text().toFloat(); + switch (cbxFilterType->currentIndex()) { case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); else calcDblQuadLPF(); @@ -157,8 +168,12 @@ void FilterSintez::slotCalcSchematic() case 1 : if (btnHighPass->isChecked()) calcMultiloopHPF(); else calcMultiloopLPF(); break; - case 2 : if (btnHighPass->isChecked()) calcSallenKeyHPF(); - else calcSallenKeyLPF(); + case 2 : { + SallenKey sk(Poles,ftyp,Fc,Kv); + sk.calcFilter(); + sk.createPartList(lst); + txtResult->setText(lst.join("\n")); + } break; case 3 : calcPassive(); break; @@ -309,7 +324,7 @@ int FilterSintez::calcInvChebyshev() lst<text().toFloat(); - - QStringList lst; - lst<<"N C1(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; - - float Wc = 2*M_PI*Fc; - - for (int k=1; k <= Nfil/2; k++) { - - float re = Poles.at(k-1).real(); - float im = Poles.at(k-1).imag(); - float B = -2.0*re; - float C = re*re + im*im; - - qDebug()<setText(lst.join("\n")); - -} - -void FilterSintez::calcSallenKeyLPF() -{ - float C1[20],C2[20],R1[20],R2[20],R3[20],R4[20]; - - float Kv = 1.0; - float Wc = 2*M_PI*Fc; - - QStringList lst; - lst<<"N C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; - - for (int k=1; k <= Nfil/2; k++) { - - float re = Poles.at(k-1).real(); - float im = Poles.at(k-1).imag(); - float B = -2.0*re; - float C = re*re + im*im; - - qDebug()<setText(lst.join("\n")); -} void FilterSintez::calcPassive() { diff --git a/mfbfilter.cpp b/mfbfilter.cpp new file mode 100644 index 0000000000..369a358610 --- /dev/null +++ b/mfbfilter.cpp @@ -0,0 +1,16 @@ +#include "mfbfilter.h" + +MFBfilter::MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) + : Filter(poles_,type_,Fcutoff,Kv_) +{ +} + +QString* MFBfilter::createSchematic() +{ + +} + +void MFBfilter::calcFilter() +{ + +} diff --git a/mfbfilter.h b/mfbfilter.h new file mode 100644 index 0000000000..d00c372313 --- /dev/null +++ b/mfbfilter.h @@ -0,0 +1,17 @@ +#ifndef MFBFILTER_H +#define MFBFILTER_H + +#include +#include +#include "filter.h" + +class MFBfilter : public Filter +{ +public: + MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); + + QString* createSchematic(); + void calcFilter(); +}; + +#endif // MFBFILTER_H diff --git a/sallenkey.cpp b/sallenkey.cpp index 3284819eef..45944fa03a 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -1,4 +1,5 @@ #include "sallenkey.h" +#include SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) : Filter(poles_, type_, Fcutoff, Kv_) @@ -8,12 +9,40 @@ SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, QString* SallenKey::createSchematic() { + RC_elements stage; + int dx = 0; + QString *s = new QString("\n"); + *s += "\n"; + *s += QString("<.AC AC1 1 30 410 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); + *s += "<.DC DC1 1 280 410 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; + *s += "\n"; + foreach (stage,Stages) { + *s += QString("\n").arg(stage.N).arg(370+dx); + *s += QString("").arg(2+stage.N).arg(320+dx); + *s += QString("").arg(200+dx); + *s += QString("").arg(100+dx); + *s += QString("").arg(270+dx); + *s += QString("").arg(330+dx); + *s += QString("").arg(410+dx); + dx += 510; + } + *s += "\n"; + *s += "\n"; + dx = 0; + foreach (stage,Stages) { + + dx += 510; + } + *s += "\n"; + return s; } void SallenKey::calcFilter() { + Stages.clear(); + switch (ftype) { case Filter::LowPass : calcSallenKeyLPF(); break; @@ -54,6 +83,7 @@ void SallenKey::calcSallenKeyLPF() } RC_elements curr_stage; + curr_stage.N = k; curr_stage.R1 = 1000*R1; curr_stage.R2 = 1000*R2; curr_stage.R3 = 1000*R3; @@ -61,42 +91,50 @@ void SallenKey::calcSallenKeyLPF() curr_stage.C1 = C1; curr_stage.C2 = C2; Stages.append(curr_stage); + } + this->calcFirstOrder(); +} - } - if (Nfil%2 != 0) { - int k = Nfil/2 + 1; +void SallenKey::calcSallenKeyHPF() +{ + float R1,R2,R3,R4,C1; + float Wc = 2*M_PI*Fc; + + + for (int k=1; k <= Nfil/2; k++) { + float re = Poles.at(k-1).real(); float im = Poles.at(k-1).imag(); + float B = -2.0*re; float C = re*re + im*im; - C1 = 10/Fc; - R1 = 1.0/(Wc*C*C1); + + qDebug()< #include "filter.h" -struct RC_elements { - float R1; - float R2; - float R3; - float R4; - float C1; - float C2; -}; class SallenKey : public Filter { private: - QVector Stages; - void calcSallenKeyHPF(); void calcSallenKeyLPF(); From 5c37ef5c745a29395cd8d49d41b50d109c9529ef Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 21 Apr 2014 15:12:38 +0400 Subject: [PATCH 14/90] Implemented basic Qucs schematic generation method --- filtersintez.cpp | 1 + sallenkey.cpp | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index b9edfa2afd..d25073e695 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -172,6 +172,7 @@ void FilterSintez::slotCalcSchematic() SallenKey sk(Poles,ftyp,Fc,Kv); sk.calcFilter(); sk.createPartList(lst); + sk.createSchematic(); txtResult->setText(lst.join("\n")); } break; diff --git a/sallenkey.cpp b/sallenkey.cpp index 45944fa03a..f7cd66f027 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -16,25 +16,53 @@ QString* SallenKey::createSchematic() *s += QString("<.AC AC1 1 30 410 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); *s += "<.DC DC1 1 280 410 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; *s += "\n"; + *s += QString("\n").arg(20+dx); + *s += QString("\n").arg(20+dx); foreach (stage,Stages) { *s += QString("\n").arg(stage.N).arg(370+dx); - *s += QString("").arg(2+stage.N).arg(320+dx); - *s += QString("").arg(200+dx); - *s += QString("").arg(100+dx); - *s += QString("").arg(270+dx); - *s += QString("").arg(330+dx); - *s += QString("").arg(410+dx); + *s += QString("\n").arg(270+dx); + *s += QString("\n").arg(320+dx); + *s += QString("\n").arg(2+stage.N).arg(320+dx); + *s += QString("\n").arg(1+stage.N).arg(200+dx); + *s += QString("\n").arg(stage.N).arg(100+dx); + *s += QString("\n").arg(1+stage.N).arg(270+dx); + *s += QString("\n").arg(stage.N).arg(330+dx); + *s += QString("\n").arg(3+stage.N).arg(410+dx); dx += 510; } *s += "\n"; *s += "\n"; dx = 0; + *s += QString("<%1 190 %2 230 \"\" 0 0 0 \"\">\n").arg(20+dx).arg(20+dx); + *s += QString("<%1 190 %2 190 \"in\" %3 160 18 \"\">\n").arg(20+dx).arg(70+dx).arg(70+dx); foreach (stage,Stages) { - + *s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); + *s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); + *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(410+dx).arg(460+dx); + *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(440+dx).arg(460+dx); + *s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); + *s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); + *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(230+dx).arg(270+dx); + *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(150+dx); + *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(170+dx); + *s += QString("<%1 70 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(150+dx); + *s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(300+dx); + *s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); + *s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(340+dx); + *s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + *s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(340+dx); + *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(380+dx); + *s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); dx += 510; } *s += "\n"; + QFile sch("filter.sch"); + sch.open(QFile::WriteOnly); + QTextStream out(&sch); + out<<*s; + sch.close(); + return s; } From b210ce24a5360b5c6607667ac7d4423426b83aef Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 21 Apr 2014 17:03:00 +0400 Subject: [PATCH 15/90] Implemented first-order stage schematic generation --- sallenkey.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/sallenkey.cpp b/sallenkey.cpp index f7cd66f027..640111c162 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -11,6 +11,9 @@ QString* SallenKey::createSchematic() { RC_elements stage; int dx = 0; + int N2ord = Nfil - Nfil%2; // number of 2-nd order stages + int N1stOrd = Nfil%2; // number of 1-st order stages + QString *s = new QString("\n"); *s += "\n"; *s += QString("<.AC AC1 1 30 410 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); @@ -18,7 +21,8 @@ QString* SallenKey::createSchematic() *s += "\n"; *s += QString("\n").arg(20+dx); *s += QString("\n").arg(20+dx); - foreach (stage,Stages) { + for (int i=1; i<=N2ord; i++) { + stage = Stages.at(i-1); *s += QString("\n").arg(stage.N).arg(370+dx); *s += QString("\n").arg(270+dx); *s += QString("\n").arg(320+dx); @@ -30,14 +34,35 @@ QString* SallenKey::createSchematic() *s += QString("\n").arg(3+stage.N).arg(410+dx); dx += 510; } + + if (N1stOrd!=0) { + stage = Stages.last(); + *s += QString("\n").arg(Nfil).arg(270+dx); + *s += QString("\n").arg(170+dx); + *s += QString("\n").arg(220+dx); + *s += QString("\n").arg(Nfil+1).arg(220+dx); + *s += QString("\n").arg(Nfil).arg(170+dx); + *s += QString("\n").arg(Nfil+2).arg(310+dx); + *s += QString("\n").arg(Nfil).arg(100+dx); + } + *s += "\n"; *s += "\n"; dx = 0; *s += QString("<%1 190 %2 230 \"\" 0 0 0 \"\">\n").arg(20+dx).arg(20+dx); *s += QString("<%1 190 %2 190 \"in\" %3 160 18 \"\">\n").arg(20+dx).arg(70+dx).arg(70+dx); - foreach (stage,Stages) { + for (int i=1; i<=N2ord; i++) { + if (i!=1) { + *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); + *s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); + *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); + } *s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); - *s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); + if (i==Nfil) { + *s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); + } else { + *s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); + } *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(410+dx).arg(460+dx); *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(440+dx).arg(460+dx); *s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); @@ -55,6 +80,25 @@ QString* SallenKey::createSchematic() *s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); dx += 510; } + + if (N1stOrd!=0) { + *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); + *s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); + *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); + + *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(170+dx); + *s += QString("<%1 160 %2 160 \"out\" %3 130 39 \"\">\n").arg(310+dx).arg(360+dx).arg(380+dx); + *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(340+dx).arg(360+dx); + *s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(360+dx); + *s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(170+dx); + *s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(170+dx); + *s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(240+dx); + *s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); + *s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(240+dx); + *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(280+dx); + *s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); + } + *s += "\n"; QFile sch("filter.sch"); From 6783554c1af9a39a49b8f7a8caa19b0bb81a845d Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 22 Apr 2014 10:54:04 +0400 Subject: [PATCH 16/90] Added SVG amplitude-frequency response to main window --- .gitignore | 2 + AFR.svg | 413 ++++++++++++++++++++++++++++++++++++++++++++++ QFilterSintez.pro | 2 +- filtersintez.cpp | 3 + filtersintez.h | 2 + 5 files changed, 421 insertions(+), 1 deletion(-) create mode 100644 AFR.svg diff --git a/.gitignore b/.gitignore index fb05f14d2e..5003808d95 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ QFilterSintez *.pro.user Makefile moc_*.cpp +*.sch +*.sch~ diff --git a/AFR.svg b/AFR.svg new file mode 100644 index 0000000000..efa4098f07 --- /dev/null +++ b/AFR.svg @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + Rp + + + Fc + + + + Fs + + + + As + K (dB) + F (Hz) + 0 + + + + + + Ap + + + + + + + + + + + + + + АЧХ фильтра + + diff --git a/QFilterSintez.pro b/QFilterSintez.pro index 2c07738826..f5ae003b2d 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui +QT += core gui svg greaterThan(QT_MAJOR_VERSION, 4): QT += widgets diff --git a/filtersintez.cpp b/filtersintez.cpp index d25073e695..2cb4aee49e 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -72,6 +72,8 @@ FilterSintez::FilterSintez(QWidget *parent) cbxFilterType->addItems(lst); connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); + imgAFR = new QSvgWidget("AFR.svg"); + imgAFR->show(); sch_pic = new QLabel; QPixmap pix("Images/dblquad.png"); sch_pic->resize(pix.size()); @@ -111,6 +113,7 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(btnCalcFiltFunc); left->addWidget(btnCalcSchematic); + right->addWidget(imgAFR); right->addWidget(sch_pic); top->addLayout(left); diff --git a/filtersintez.h b/filtersintez.h index 5ae086ae39..5706d247e7 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -2,6 +2,7 @@ #define FILTERSINTEZ_H #include +#include #include #include @@ -35,6 +36,7 @@ class FilterSintez : public QMainWindow QLabel *lblResult; QTextEdit *txtResult; + QSvgWidget *imgAFR; QLabel *lblSch; QRadioButton *btnLowPass; From 284f63709e09dde3d07debdbe0238d083508d8d3 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 22 Apr 2014 19:23:00 +0400 Subject: [PATCH 17/90] First order schematic generation moved to filter.cpp --- filter.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ filter.h | 4 ++++ filtersintez.cpp | 20 +++++++++---------- sallenkey.cpp | 36 ++++++++++------------------------ 4 files changed, 75 insertions(+), 36 deletions(-) diff --git a/filter.cpp b/filter.cpp index 3243f2a8bb..bdf996f0ae 100644 --- a/filter.cpp +++ b/filter.cpp @@ -61,3 +61,54 @@ void Filter::createPartList(QStringList &lst) " "+QString::number(stage.R4); } } + +void Filter::createFirstOrderComponents(QString &s,RC_elements stage,int dx) +{ + s += QString("\n").arg(Nfil).arg(270+dx); + s += QString("\n").arg(170+dx); + s += QString("\n").arg(220+dx); + s += QString("\n").arg(Nfil+1).arg(220+dx); + s += QString("\n").arg(Nfil).arg(170+dx); + s += QString("\n").arg(Nfil+2).arg(310+dx); + s += QString("\n").arg(Nfil).arg(100+dx); +} + +void Filter::createFirstOrderWires(QString &s, int dx) +{ + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); + s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); + s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); + + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(170+dx); + s += QString("<%1 160 %2 160 \"out\" %3 130 39 \"\">\n").arg(310+dx).arg(360+dx).arg(380+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(340+dx).arg(360+dx); + s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(360+dx); + s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(170+dx); + s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(170+dx); + s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(240+dx); + s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); + s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(240+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(280+dx); + s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); +} + + +float Filter::autoscaleCapacitor(float C, QString &suffix) +{ + float C1 = C*1e-6; + + if (C1>=1e-7) { + suffix = "uF"; + return C1*1e6; + } + + if ((C1<1e-7)&&(C1>=1e-8)) { + suffix = "nF"; + return C1*1e9; + } + + if (C1<1e-8) { + suffix = "pF"; + return C1*1e12; + } +} diff --git a/filter.h b/filter.h index 887d5f49a1..b1f5ef7914 100644 --- a/filter.h +++ b/filter.h @@ -29,6 +29,10 @@ class Filter int Nfil; float Fc,Kv; + void createFirstOrderComponents(QString &s,RC_elements stage, int dx); + void createFirstOrderWires(QString &s, int dx); + float autoscaleCapacitor(float C, QString &suffix); + public: diff --git a/filtersintez.cpp b/filtersintez.cpp index 2cb4aee49e..fa63be24d5 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -12,12 +12,12 @@ FilterSintez::FilterSintez(QWidget *parent) QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); lblInputData = new QLabel(tr("Входные данные")); - lblA1 = new QLabel(tr("Затухание фильтра в полосе пропускания, A1")); - lblA2 = new QLabel(tr("Затухание фильтра в полосе задерживания, A2")); - lblF1 = new QLabel(tr("Частота среза фильтра в полосе пропускания, F1")); - lblF2 = new QLabel(tr("Частота фильтра в полосе задерживания, F2")); - lblRpl1 = new QLabel(tr("амплитуда пульсаций в полосе пропускания (дБ)")); - lblRpl2 = new QLabel(tr("Амплитуда пульсаций в полосе задерживания (дБ)")); + lblA1 = new QLabel(tr("Затухание фильтра в полосе пропускания, Ap")); + lblA2 = new QLabel(tr("Минимальное затухание фильтра в полосе задерживания, As")); + lblF1 = new QLabel(tr("Частота среза фильтра, Fc (Гц)")); + lblF2 = new QLabel(tr("Начало полосы задерживания, Fs (Гц)")); + lblRpl1 = new QLabel(tr("Амплитуда пульсаций в полосе пропускания Rp(дБ)")); + //lblRpl2 = new QLabel(tr("Амплитуда пульсаций в полосе задерживания (дБ)")); lblKv = new QLabel(tr("Усиление фильтра, Kv")); @@ -32,8 +32,8 @@ FilterSintez::FilterSintez(QWidget *parent) edtF2->setValidator(val1); edtPassbRpl = new QLineEdit("3"); edtPassbRpl->setValidator(val1); - edtStopbRpl = new QLineEdit("3"); - edtStopbRpl->setValidator(val1); + //edtStopbRpl = new QLineEdit("3"); + //edtStopbRpl->setValidator(val1); edtKv = new QLineEdit("2"); edtKv->setValidator(val1); @@ -95,8 +95,8 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(edtF2); left->addWidget(lblRpl1); left->addWidget(edtPassbRpl); - left->addWidget(lblRpl2); - left->addWidget(edtStopbRpl); + //left->addWidget(lblRpl2); + //left->addWidget(edtStopbRpl); left->addWidget(lblKv); left->addWidget(edtKv); left->addWidget(lblTyp); diff --git a/sallenkey.cpp b/sallenkey.cpp index 640111c162..a4be3f02d5 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -11,7 +11,7 @@ QString* SallenKey::createSchematic() { RC_elements stage; int dx = 0; - int N2ord = Nfil - Nfil%2; // number of 2-nd order stages + int N2ord = Nfil/2; // number of 2-nd order stages int N1stOrd = Nfil%2; // number of 1-st order stages QString *s = new QString("\n"); @@ -23,11 +23,16 @@ QString* SallenKey::createSchematic() *s += QString("\n").arg(20+dx); for (int i=1; i<=N2ord; i++) { stage = Stages.at(i-1); + qDebug()<\n").arg(stage.N).arg(370+dx); *s += QString("\n").arg(270+dx); *s += QString("\n").arg(320+dx); *s += QString("\n").arg(2+stage.N).arg(320+dx); - *s += QString("\n").arg(1+stage.N).arg(200+dx); + *s += QString("\n").arg(1+stage.N).arg(200+dx).arg(C2,0,'g',3).arg(suffix1); *s += QString("\n").arg(stage.N).arg(100+dx); *s += QString("\n").arg(1+stage.N).arg(270+dx); *s += QString("\n").arg(stage.N).arg(330+dx); @@ -36,14 +41,7 @@ QString* SallenKey::createSchematic() } if (N1stOrd!=0) { - stage = Stages.last(); - *s += QString("\n").arg(Nfil).arg(270+dx); - *s += QString("\n").arg(170+dx); - *s += QString("\n").arg(220+dx); - *s += QString("\n").arg(Nfil+1).arg(220+dx); - *s += QString("\n").arg(Nfil).arg(170+dx); - *s += QString("\n").arg(Nfil+2).arg(310+dx); - *s += QString("\n").arg(Nfil).arg(100+dx); + createFirstOrderComponents(*s,stage,dx); } *s += "\n"; @@ -58,7 +56,7 @@ QString* SallenKey::createSchematic() *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); } *s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); - if (i==Nfil) { + if ((2*i)==Nfil) { *s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); } else { *s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); @@ -82,21 +80,7 @@ QString* SallenKey::createSchematic() } if (N1stOrd!=0) { - *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); - *s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); - *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); - - *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(170+dx); - *s += QString("<%1 160 %2 160 \"out\" %3 130 39 \"\">\n").arg(310+dx).arg(360+dx).arg(380+dx); - *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(340+dx).arg(360+dx); - *s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(360+dx); - *s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(170+dx); - *s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(170+dx); - *s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(170+dx).arg(240+dx); - *s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); - *s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(240+dx); - *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(280+dx); - *s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); + createFirstOrderWires(*s,dx); } *s += "\n"; From 94eb2dc69ec0a84b0dd53665c76252a7aba23238 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 23 Apr 2014 14:10:31 +0400 Subject: [PATCH 18/90] Implemented working high-pass SalleKey filter generation --- filter.cpp | 7 ++++--- sallenkey.cpp | 16 +++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/filter.cpp b/filter.cpp index bdf996f0ae..1a7ea6080f 100644 --- a/filter.cpp +++ b/filter.cpp @@ -99,16 +99,17 @@ float Filter::autoscaleCapacitor(float C, QString &suffix) if (C1>=1e-7) { suffix = "uF"; - return C1*1e6; + C1 *= 1e6; } if ((C1<1e-7)&&(C1>=1e-8)) { suffix = "nF"; - return C1*1e9; + C1 *= 1e9; } if (C1<1e-8) { suffix = "pF"; - return C1*1e12; + C1 *= 1e12; } + return C1; } diff --git a/sallenkey.cpp b/sallenkey.cpp index a4be3f02d5..c42ab6c109 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -9,6 +9,8 @@ SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, QString* SallenKey::createSchematic() { + int const N_R=4; // number of resisitors in 2-order Sallen-Key stage + int const N_C=2; // number of capacitors in 2-order Sallen-Key stage RC_elements stage; int dx = 0; int N2ord = Nfil/2; // number of 2-nd order stages @@ -27,16 +29,16 @@ QString* SallenKey::createSchematic() QString suffix1, suffix2; float C1 = autoscaleCapacitor(stage.C1,suffix1); float C2 = autoscaleCapacitor(stage.C2,suffix2); - qDebug()<\n").arg(stage.N).arg(370+dx); *s += QString("\n").arg(270+dx); *s += QString("\n").arg(320+dx); - *s += QString("\n").arg(2+stage.N).arg(320+dx); - *s += QString("\n").arg(1+stage.N).arg(200+dx).arg(C2,0,'g',3).arg(suffix1); - *s += QString("\n").arg(stage.N).arg(100+dx); - *s += QString("\n").arg(1+stage.N).arg(270+dx); - *s += QString("\n").arg(stage.N).arg(330+dx); - *s += QString("\n").arg(3+stage.N).arg(410+dx); + *s += QString("\n").arg(3+(i-1)*N_R).arg(320+dx).arg(stage.R3,0,'f',3); + *s += QString("\n").arg(2+(i-1)*N_C).arg(200+dx).arg(C2,0,'f',3).arg(suffix2); + *s += QString("\n").arg(1+(i-1)*N_C).arg(100+dx).arg(C1,0,'f',3).arg(suffix1); + *s += QString("\n").arg(2+(i-1)*N_R).arg(270+dx).arg(stage.R2,0,'f',3); + *s += QString("\n").arg(1+(i-1)*N_R).arg(330+dx).arg(stage.R1,0,'f',3); + *s += QString("\n").arg(4+(i-1)*N_R).arg(410+dx).arg(stage.R4,0,'f',3); dx += 510; } From a197096432803cfb245413f05534ff434f2daa6c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 23 Apr 2014 17:17:12 +0400 Subject: [PATCH 19/90] Implemented low-pass sallen-key schematimatic sintez --- filter.cpp | 10 +- filter.h | 2 +- filtersintez.cpp | 3 +- sallenkey.cpp | 251 ++++++++++++++++++++++++++++++++--------------- sallenkey.h | 4 +- 5 files changed, 183 insertions(+), 87 deletions(-) diff --git a/filter.cpp b/filter.cpp index 1a7ea6080f..9305f8cd59 100644 --- a/filter.cpp +++ b/filter.cpp @@ -64,13 +64,15 @@ void Filter::createPartList(QStringList &lst) void Filter::createFirstOrderComponents(QString &s,RC_elements stage,int dx) { + QString suf; + float C1 = autoscaleCapacitor(stage.C1,suf); s += QString("\n").arg(Nfil).arg(270+dx); s += QString("\n").arg(170+dx); s += QString("\n").arg(220+dx); - s += QString("\n").arg(Nfil+1).arg(220+dx); - s += QString("\n").arg(Nfil).arg(170+dx); - s += QString("\n").arg(Nfil+2).arg(310+dx); - s += QString("\n").arg(Nfil).arg(100+dx); + s += QString("\n").arg(Nfil+1).arg(220+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(Nfil).arg(170+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(Nfil+2).arg(310+dx).arg(stage.R3,0,'f',3); + s += QString("\n").arg(Nfil).arg(100+dx).arg(C1,0,'f',3).arg(suf); } void Filter::createFirstOrderWires(QString &s, int dx) diff --git a/filter.h b/filter.h index b1f5ef7914..db4676d2f5 100644 --- a/filter.h +++ b/filter.h @@ -43,7 +43,7 @@ class Filter void createPartList(QStringList &lst); - virtual QString* createSchematic() + virtual void createSchematic(QString &s) { } diff --git a/filtersintez.cpp b/filtersintez.cpp index fa63be24d5..f521b38dcf 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -172,10 +172,11 @@ void FilterSintez::slotCalcSchematic() else calcMultiloopLPF(); break; case 2 : { + QString s; SallenKey sk(Poles,ftyp,Fc,Kv); sk.calcFilter(); sk.createPartList(lst); - sk.createSchematic(); + sk.createSchematic(s); txtResult->setText(lst.join("\n")); } break; diff --git a/sallenkey.cpp b/sallenkey.cpp index c42ab6c109..c54edee511 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -7,93 +7,22 @@ SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, } -QString* SallenKey::createSchematic() +void SallenKey::createSchematic(QString &s) { - int const N_R=4; // number of resisitors in 2-order Sallen-Key stage - int const N_C=2; // number of capacitors in 2-order Sallen-Key stage - RC_elements stage; - int dx = 0; - int N2ord = Nfil/2; // number of 2-nd order stages - int N1stOrd = Nfil%2; // number of 1-st order stages - - QString *s = new QString("\n"); - *s += "\n"; - *s += QString("<.AC AC1 1 30 410 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); - *s += "<.DC DC1 1 280 410 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; - *s += "\n"; - *s += QString("\n").arg(20+dx); - *s += QString("\n").arg(20+dx); - for (int i=1; i<=N2ord; i++) { - stage = Stages.at(i-1); - qDebug()<\n").arg(stage.N).arg(370+dx); - *s += QString("\n").arg(270+dx); - *s += QString("\n").arg(320+dx); - *s += QString("\n").arg(3+(i-1)*N_R).arg(320+dx).arg(stage.R3,0,'f',3); - *s += QString("\n").arg(2+(i-1)*N_C).arg(200+dx).arg(C2,0,'f',3).arg(suffix2); - *s += QString("\n").arg(1+(i-1)*N_C).arg(100+dx).arg(C1,0,'f',3).arg(suffix1); - *s += QString("\n").arg(2+(i-1)*N_R).arg(270+dx).arg(stage.R2,0,'f',3); - *s += QString("\n").arg(1+(i-1)*N_R).arg(330+dx).arg(stage.R1,0,'f',3); - *s += QString("\n").arg(4+(i-1)*N_R).arg(410+dx).arg(stage.R4,0,'f',3); - dx += 510; - } - - if (N1stOrd!=0) { - createFirstOrderComponents(*s,stage,dx); - } - - *s += "\n"; - *s += "\n"; - dx = 0; - *s += QString("<%1 190 %2 230 \"\" 0 0 0 \"\">\n").arg(20+dx).arg(20+dx); - *s += QString("<%1 190 %2 190 \"in\" %3 160 18 \"\">\n").arg(20+dx).arg(70+dx).arg(70+dx); - for (int i=1; i<=N2ord; i++) { - if (i!=1) { - *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); - *s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); - *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); - } - *s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); - if ((2*i)==Nfil) { - *s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); - } else { - *s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); - } - *s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(410+dx).arg(460+dx); - *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(440+dx).arg(460+dx); - *s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); - *s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); - *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(230+dx).arg(270+dx); - *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(150+dx); - *s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(170+dx); - *s += QString("<%1 70 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(150+dx); - *s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(300+dx); - *s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); - *s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(340+dx); - *s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); - *s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(340+dx); - *s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(380+dx); - *s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); - dx += 510; - } - - if (N1stOrd!=0) { - createFirstOrderWires(*s,dx); + switch (ftype) { + case Filter::HighPass : createHighPassSchematic(s); + break; + case Filter::LowPass : createLowPassSchematic(s); + break; + default: break; } - *s += "\n"; - QFile sch("filter.sch"); sch.open(QFile::WriteOnly); QTextStream out(&sch); - out<<*s; + out<\n").arg((10.0*Fc)/1000.0); + s += "<.DC DC1 1 280 410 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; + s += "\n"; + s += QString("\n").arg(20+dx); + s += QString("\n").arg(20+dx); + for (int i=1; i<=N2ord; i++) { + stage = Stages.at(i-1); + qDebug()<\n").arg(stage.N).arg(370+dx); + s += QString("\n").arg(270+dx); + s += QString("\n").arg(320+dx); + s += QString("\n").arg(3+(i-1)*N_R).arg(320+dx).arg(stage.R3,0,'f',3); + s += QString("\n").arg(2+(i-1)*N_C).arg(200+dx).arg(C2,0,'f',3).arg(suffix2); + s += QString("\n").arg(1+(i-1)*N_C).arg(100+dx).arg(C1,0,'f',3).arg(suffix1); + s += QString("\n").arg(2+(i-1)*N_R).arg(270+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(1+(i-1)*N_R).arg(330+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(4+(i-1)*N_R).arg(410+dx).arg(stage.R4,0,'f',3); + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderComponents(s,stage,dx); + } + + s += "\n"; + s += "\n"; + dx = 0; + s += QString("<%1 190 %2 230 \"\" 0 0 0 \"\">\n").arg(20+dx).arg(20+dx); + s += QString("<%1 190 %2 190 \"in\" %3 160 18 \"\">\n").arg(20+dx).arg(70+dx).arg(70+dx); + for (int i=1; i<=N2ord; i++) { + if (i!=1) { + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); + s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); + s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); + } + s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); + if ((2*i)==Nfil) { + s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); + } else { + s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); + } + s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(410+dx).arg(460+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(440+dx).arg(460+dx); + s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); + s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(230+dx).arg(270+dx); + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(150+dx); + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(170+dx); + s += QString("<%1 70 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(150+dx); + s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(300+dx); + s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); + s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(340+dx); + s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(340+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(380+dx); + s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderWires(s,dx); + } + + s += "\n"; +} + +void SallenKey::createLowPassSchematic(QString &s) +{ + int const N_R=4; // number of resisitors in 2-order Sallen-Key stage + int const N_C=2; // number of capacitors in 2-order Sallen-Key stage + RC_elements stage; + int dx = 0; + int N2ord = Nfil/2; // number of 2-nd order stages + int N1stOrd = Nfil%2; // number of 1-st order stages + + s += "\n"; + s += "\n"; + s += QString("<.AC AC1 1 30 410 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); + s += "<.DC DC1 1 280 410 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; + s += "\n"; + s += QString("\n").arg(20+dx); + s += QString("\n").arg(20+dx); + for (int i=1; i<=N2ord; i++) { + stage = Stages.at(i-1); + qDebug()<\n").arg(stage.N).arg(370+dx); + s += QString("\n").arg(270+dx); + s += QString("\n").arg(320+dx); + s += QString("\n").arg(2+(i-1)*N_C).arg(330+dx).arg(C2,0,'f',3).arg(suffix2); + s += QString("\n").arg(1+(i-1)*N_C).arg(270+dx).arg(C1,0,'f',3).arg(suffix1); + s += QString("\n").arg(2+(i-1)*N_R).arg(200+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(1+(i-1)*N_R).arg(100+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(3+(i-1)*N_R).arg(320+dx).arg(stage.R3,0,'f',3); + s += QString("\n").arg(4+(i-1)*N_R).arg(410+dx).arg(stage.R4,0,'f',3); + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderComponents(s,stage,dx); + } + + s += "\n"; + s += "\n"; + dx = 0; + s += QString("<%1 190 %2 230 \"\" 0 0 0 \"\">\n").arg(20+dx).arg(20+dx); + s += QString("<%1 190 %2 190 \"in\" %3 160 18 \"\">\n").arg(20+dx).arg(70+dx).arg(70+dx); + for (int i=1; i<=N2ord; i++) { + if (i!=1) { + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); + s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); + s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); + } + s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); + if ((2*i)==Nfil) { + s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); + } else { + s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); + } + s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(410+dx).arg(460+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(440+dx).arg(460+dx); + s += QString("<%1 160 %2 260 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); + s += QString("<%1 190 %2 210 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(230+dx).arg(270+dx); + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(150+dx); + s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(170+dx); + s += QString("<%1 70 %2 190 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(150+dx); + s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(150+dx).arg(300+dx); + s += QString("<%1 140 %2 190 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(270+dx); + s += QString("<%1 140 %2 140 \"\" 0 0 0 \"\">\n").arg(270+dx).arg(340+dx); + s += QString("<%1 180 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + s += QString("<%1 180 %2 180 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(340+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(380+dx); + s += QString("<%1 260 %2 310 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderWires(s,dx); + } + + s += "\n"; +} diff --git a/sallenkey.h b/sallenkey.h index 731a54f023..12ae145818 100644 --- a/sallenkey.h +++ b/sallenkey.h @@ -14,11 +14,13 @@ class SallenKey : public Filter void calcSallenKeyHPF(); void calcSallenKeyLPF(); + void createHighPassSchematic(QString &s); + void createLowPassSchematic(QString &s); public: SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); - QString* createSchematic(); + void createSchematic(QString &s); void calcFilter(); }; From bc930402f1bd06202a89c10b2501ee574ba8a13e Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 24 Apr 2014 19:32:32 +0400 Subject: [PATCH 20/90] First order stage schematic is generated all right --- filter.cpp | 26 ++++++++++++++++++++------ filter.h | 4 +++- sallenkey.cpp | 8 ++++++-- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/filter.cpp b/filter.cpp index 9305f8cd59..215e6a91cc 100644 --- a/filter.cpp +++ b/filter.cpp @@ -62,17 +62,31 @@ void Filter::createPartList(QStringList &lst) } } -void Filter::createFirstOrderComponents(QString &s,RC_elements stage,int dx) +void Filter::createFirstOrderComponentsHPF(QString &s,RC_elements stage,int dx) { QString suf; float C1 = autoscaleCapacitor(stage.C1,suf); - s += QString("\n").arg(Nfil).arg(270+dx); + s += QString("\n").arg(Nopamp+1).arg(270+dx); s += QString("\n").arg(170+dx); s += QString("\n").arg(220+dx); - s += QString("\n").arg(Nfil+1).arg(220+dx).arg(stage.R2,0,'f',3); - s += QString("\n").arg(Nfil).arg(170+dx).arg(stage.R1,0,'f',3); - s += QString("\n").arg(Nfil+2).arg(310+dx).arg(stage.R3,0,'f',3); - s += QString("\n").arg(Nfil).arg(100+dx).arg(C1,0,'f',3).arg(suf); + s += QString("\n").arg(Nr+2).arg(220+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(Nr+1).arg(170+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(Nr+3).arg(310+dx).arg(stage.R3,0,'f',3); + s += QString("\n").arg(Nc+1).arg(100+dx).arg(C1,0,'f',3).arg(suf); +} + + +void Filter::createFirstOrderComponentsLPF(QString &s,RC_elements stage,int dx) +{ + QString suf; + float C1 = autoscaleCapacitor(stage.C1,suf); + s += QString("\n").arg(Nopamp+1).arg(270+dx); + s += QString("\n").arg(170+dx); + s += QString("\n").arg(220+dx); + s += QString("\n").arg(Nr+2).arg(220+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(Nr+1).arg(100+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(Nr+3).arg(310+dx).arg(stage.R3,0,'f',3); + s += QString("\n").arg(Nc+1).arg(170+dx).arg(C1,0,'f',3).arg(suf); } void Filter::createFirstOrderWires(QString &s, int dx) diff --git a/filter.h b/filter.h index db4676d2f5..2868bbf79e 100644 --- a/filter.h +++ b/filter.h @@ -28,8 +28,10 @@ class Filter Filter::FType ftype; int Nfil; float Fc,Kv; + int Nr,Nc,Nopamp; - void createFirstOrderComponents(QString &s,RC_elements stage, int dx); + void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); + void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx); void createFirstOrderWires(QString &s, int dx); float autoscaleCapacitor(float C, QString &suffix); diff --git a/sallenkey.cpp b/sallenkey.cpp index c54edee511..386a13c653 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -38,6 +38,10 @@ void SallenKey::calcFilter() default: break; } + + Nr = 4*(Nfil/2); + Nc = 2*(Nfil/2); + Nopamp = Nfil/2; } @@ -162,7 +166,7 @@ void SallenKey::createHighPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderComponents(s,stage,dx); + createFirstOrderComponentsHPF(s,stage,dx); } s += "\n"; @@ -243,7 +247,7 @@ void SallenKey::createLowPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderComponents(s,stage,dx); + createFirstOrderComponentsLPF(s,stage,dx); } s += "\n"; From 8840e5b1217c37600f6c268618d4ab7132bb6374 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 25 Apr 2014 19:28:12 +0400 Subject: [PATCH 21/90] Implemented MFB filter calculation --- filtersintez.cpp | 11 +++++++---- mfbfilter.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++- mfbfilter.h | 6 +++++- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index f521b38dcf..f2320b38fc 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -1,5 +1,6 @@ #include "filtersintez.h" #include "sallenkey.h" +#include "mfbfilter.h" #include @@ -168,8 +169,12 @@ void FilterSintez::slotCalcSchematic() case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); else calcDblQuadLPF(); break; - case 1 : if (btnHighPass->isChecked()) calcMultiloopHPF(); - else calcMultiloopLPF(); + case 1 : { + MFBfilter mfb(Poles,ftyp,Fc,Kv); + mfb.calcFilter(); + mfb.createPartList(lst); + txtResult->setText(lst.join("\n")); + } break; case 2 : { QString s; @@ -229,11 +234,9 @@ int FilterSintez::calcChebyshev() float a = sinh((asinh(1/eps))/N); float b = cosh((asinh(1/eps))/N); - qDebug()< > poles_, Filter::FType type_, { } -QString* MFBfilter::createSchematic() +void MFBfilter::createSchematic(QString &s) { } void MFBfilter::calcFilter() { + Stages.clear(); + switch (ftype) { + case Filter::LowPass : calcMFB_LPF(); + break; + case Filter::HighPass : calcMFB_HPF(); + break; + default: + break; + } + + Nr = 3*(Nfil/2); + Nc = 2*(Nfil/2); + Nopamp = Nfil/2; +} + +void MFBfilter::calcMFB_HPF() +{ + +} + +void MFBfilter::calcMFB_LPF() +{ + float R1,R2,R3,C1,C2; + float Wc = 2*M_PI*Fc; + + for (int k=1; k <= Nfil/2; k++) { + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float B = -2.0*re; + float C = re*re + im*im; + + qDebug()< > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); - QString* createSchematic(); + void createSchematic(QString &s); void calcFilter(); }; From e30683994171e2aaadf71247231052f74ae4877c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 26 Apr 2014 14:38:57 +0400 Subject: [PATCH 22/90] Implemented filter gain given in dB --- filter.h | 1 + filtersintez.cpp | 3 ++- mfbfilter.cpp | 16 ++++++++-------- mfbfilter.h | 4 ++-- sallenkey.cpp | 8 ++++---- sallenkey.h | 4 ++-- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/filter.h b/filter.h index 2868bbf79e..702a86c0b8 100644 --- a/filter.h +++ b/filter.h @@ -23,6 +23,7 @@ class Filter protected: QVector< std::complex > Poles; + QVector< std::complex > Zeros; QVector Stages; Filter::FType ftype; diff --git a/filtersintez.cpp b/filtersintez.cpp index f2320b38fc..4ea3d49c71 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -163,7 +163,8 @@ void FilterSintez::slotCalcSchematic() QStringList lst; - float Kv = edtKv->text().toFloat(); + float G = edtKv->text().toFloat(); + float Kv = pow(10,G/20.0); switch (cbxFilterType->currentIndex()) { case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); diff --git a/mfbfilter.cpp b/mfbfilter.cpp index e8f9c3ca55..644ca3694e 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -15,9 +15,9 @@ void MFBfilter::calcFilter() Stages.clear(); switch (ftype) { - case Filter::LowPass : calcMFB_LPF(); + case Filter::LowPass : calcLowPass(); break; - case Filter::HighPass : calcMFB_HPF(); + case Filter::HighPass : calcHighPass(); break; default: break; @@ -28,12 +28,12 @@ void MFBfilter::calcFilter() Nopamp = Nfil/2; } -void MFBfilter::calcMFB_HPF() +void MFBfilter::calcHighPass() { } -void MFBfilter::calcMFB_LPF() +void MFBfilter::calcLowPass() { float R1,R2,R3,C1,C2; float Wc = 2*M_PI*Fc; @@ -46,7 +46,7 @@ void MFBfilter::calcMFB_LPF() qDebug()< > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); diff --git a/sallenkey.cpp b/sallenkey.cpp index 386a13c653..a7b7c77b6c 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -31,9 +31,9 @@ void SallenKey::calcFilter() Stages.clear(); switch (ftype) { - case Filter::LowPass : calcSallenKeyLPF(); + case Filter::LowPass : calcLowPass(); break; - case Filter::HighPass : calcSallenKeyHPF(); + case Filter::HighPass : calcHighPass(); break; default: break; @@ -45,7 +45,7 @@ void SallenKey::calcFilter() } -void SallenKey::calcSallenKeyLPF() +void SallenKey::calcLowPass() { float R1,R2,R3,R4,C1,C2; float Wc = 2*M_PI*Fc; @@ -88,7 +88,7 @@ void SallenKey::calcSallenKeyLPF() } -void SallenKey::calcSallenKeyHPF() +void SallenKey::calcHighPass() { float R1,R2,R3,R4,C1; float Wc = 2*M_PI*Fc; diff --git a/sallenkey.h b/sallenkey.h index 12ae145818..137081a469 100644 --- a/sallenkey.h +++ b/sallenkey.h @@ -12,8 +12,8 @@ class SallenKey : public Filter private: - void calcSallenKeyHPF(); - void calcSallenKeyLPF(); + void calcHighPass(); + void calcLowPass(); void createHighPassSchematic(QString &s); void createLowPassSchematic(QString &s); From 32ada64e37605e91241f8490522ee231b46e2348 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 26 Apr 2014 17:39:56 +0400 Subject: [PATCH 23/90] Noteven order fiter sintez works now correct --- filter.cpp | 7 ++++--- filtersintez.cpp | 2 +- sallenkey.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/filter.cpp b/filter.cpp index 215e6a91cc..4c136b39d4 100644 --- a/filter.cpp +++ b/filter.cpp @@ -23,11 +23,12 @@ void Filter::calcFirstOrder() int k = Nfil/2 + 1; float Wc = 2*M_PI*Fc; float re = Poles.at(k-1).real(); - float im = Poles.at(k-1).imag(); - float C = re*re + im*im; + //float im = Poles.at(k-1).imag(); + //float C = re*re + im*im; + float C = -re; float C1 = 10/Fc; float R1 = 1.0/(Wc*C*C1); - + qDebug()<\n").arg(stage.N).arg(370+dx); s += QString("\n").arg(270+dx); s += QString("\n").arg(320+dx); @@ -166,7 +166,8 @@ void SallenKey::createHighPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderComponentsHPF(s,stage,dx); + qDebug()<\n").arg(stage.N).arg(370+dx); s += QString("\n").arg(270+dx); s += QString("\n").arg(320+dx); @@ -247,7 +247,7 @@ void SallenKey::createLowPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderComponentsLPF(s,stage,dx); + createFirstOrderComponentsLPF(s,Stages.last(),dx); } s += "\n"; From 86f2208d6cf6d4de80938c93f06794c0f03518a0 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 27 Apr 2014 12:01:31 +0400 Subject: [PATCH 24/90] calcFilter function moved to filter.cpp to remove duplicate code --- filter.cpp | 30 ++++++++++++++++++++++++++++++ filter.h | 11 ++++++----- mfbfilter.cpp | 21 +++------------------ mfbfilter.h | 2 +- sallenkey.cpp | 23 +++-------------------- sallenkey.h | 2 +- 6 files changed, 44 insertions(+), 45 deletions(-) diff --git a/filter.cpp b/filter.cpp index 4c136b39d4..9aa60efae0 100644 --- a/filter.cpp +++ b/filter.cpp @@ -14,6 +14,36 @@ Filter::~Filter() } + +void Filter::calcFilter() +{ + Stages.clear(); + + switch (ftype) { + case Filter::LowPass : calcLowPass(); + break; + case Filter::HighPass : calcHighPass(); + break; + default: + break; + } + + Nr = Nr1*(Nfil/2); + Nc = Nc1*(Nfil/2); + Nopamp = Nop1*Nfil/2; +} + + +void Filter::calcHighPass() +{ + +} + +void Filter::calcLowPass() +{ + +} + void Filter::calcFirstOrder() { if (Nfil%2 != 0) { diff --git a/filter.h b/filter.h index 702a86c0b8..6053830917 100644 --- a/filter.h +++ b/filter.h @@ -29,12 +29,16 @@ class Filter Filter::FType ftype; int Nfil; float Fc,Kv; - int Nr,Nc,Nopamp; + int Nr,Nc,Nopamp; // total number of R,C, opamp + + int Nr1,Nc1,Nop1; // number of R,C, opamp per stage void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx); void createFirstOrderWires(QString &s, int dx); float autoscaleCapacitor(float C, QString &suffix); + virtual void calcHighPass(); + virtual void calcLowPass(); public: @@ -51,10 +55,7 @@ class Filter } - virtual void calcFilter() - { - - } + virtual void calcFilter(); }; diff --git a/mfbfilter.cpp b/mfbfilter.cpp index 644ca3694e..09b13856a0 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -3,6 +3,9 @@ MFBfilter::MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) : Filter(poles_,type_,Fcutoff,Kv_) { + Nr1 = 3; + Nc1 = 2; + Nop1 = 1; } void MFBfilter::createSchematic(QString &s) @@ -10,24 +13,6 @@ void MFBfilter::createSchematic(QString &s) } -void MFBfilter::calcFilter() -{ - Stages.clear(); - - switch (ftype) { - case Filter::LowPass : calcLowPass(); - break; - case Filter::HighPass : calcHighPass(); - break; - default: - break; - } - - Nr = 3*(Nfil/2); - Nc = 2*(Nfil/2); - Nopamp = Nfil/2; -} - void MFBfilter::calcHighPass() { diff --git a/mfbfilter.h b/mfbfilter.h index a48ee4a131..b0f5fffa3b 100644 --- a/mfbfilter.h +++ b/mfbfilter.h @@ -15,7 +15,7 @@ class MFBfilter : public Filter MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); void createSchematic(QString &s); - void calcFilter(); + }; #endif // MFBFILTER_H diff --git a/sallenkey.cpp b/sallenkey.cpp index 80911da2b9..65ce937004 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -4,7 +4,9 @@ SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) : Filter(poles_, type_, Fcutoff, Kv_) { - + Nr1 = 4; + Nc1 = 2; + Nop1 = 1; } void SallenKey::createSchematic(QString &s) @@ -26,25 +28,6 @@ void SallenKey::createSchematic(QString &s) } -void SallenKey::calcFilter() -{ - Stages.clear(); - - switch (ftype) { - case Filter::LowPass : calcLowPass(); - break; - case Filter::HighPass : calcHighPass(); - break; - default: - break; - } - - Nr = 4*(Nfil/2); - Nc = 2*(Nfil/2); - Nopamp = Nfil/2; -} - - void SallenKey::calcLowPass() { float R1,R2,R3,R4,C1,C2; diff --git a/sallenkey.h b/sallenkey.h index 137081a469..2d162a4740 100644 --- a/sallenkey.h +++ b/sallenkey.h @@ -21,7 +21,7 @@ class SallenKey : public Filter SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); void createSchematic(QString &s); - void calcFilter(); + }; #endif // SALLENKEY_H From cf4ce3bf6a76f655c7c49def4077ce53807753b9 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 27 Apr 2014 16:47:58 +0400 Subject: [PATCH 25/90] Implemented multiple feedback filter schematic --- filter.cpp | 26 ++++++++++ filter.h | 6 +-- filtersintez.cpp | 4 +- mfbfilter.cpp | 132 ++++++++++++++++++++++++++++++++++++++++++++--- mfbfilter.h | 6 +-- sallenkey.cpp | 18 ------- sallenkey.h | 4 +- 7 files changed, 162 insertions(+), 34 deletions(-) diff --git a/filter.cpp b/filter.cpp index 9aa60efae0..0e1ba9bec2 100644 --- a/filter.cpp +++ b/filter.cpp @@ -14,6 +14,32 @@ Filter::~Filter() } +void Filter::createSchematic(QString &s) +{ + switch (ftype) { + case Filter::HighPass : createHighPassSchematic(s); + break; + case Filter::LowPass : createLowPassSchematic(s); + break; + default: break; + } + + QFile sch("filter.sch"); + sch.open(QFile::WriteOnly); + QTextStream out(&sch); + out<setValidator(val1); //edtStopbRpl = new QLineEdit("3"); //edtStopbRpl->setValidator(val1); - edtKv = new QLineEdit("2"); + edtKv = new QLineEdit("0"); edtKv->setValidator(val1); lblTyp = new QLabel(tr("Рассчитать фильтр:")); @@ -171,9 +171,11 @@ void FilterSintez::slotCalcSchematic() else calcDblQuadLPF(); break; case 1 : { + QString s; MFBfilter mfb(Poles,ftyp,Fc,Kv); mfb.calcFilter(); mfb.createPartList(lst); + mfb.createSchematic(s); txtResult->setText(lst.join("\n")); } break; diff --git a/mfbfilter.cpp b/mfbfilter.cpp index 09b13856a0..7cd0573cda 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -3,18 +3,134 @@ MFBfilter::MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) : Filter(poles_,type_,Fcutoff,Kv_) { - Nr1 = 3; - Nc1 = 2; + switch (ftype) { + case Filter::LowPass : + Nr1=3; + Nc1=2; + break; + case Filter::HighPass : + Nr1=2; + Nc1=3; + break; + default: + break; + } + + //Nr1 = 3; + //Nc1 = 2; Nop1 = 1; } -void MFBfilter::createSchematic(QString &s) +void MFBfilter::createLowPassSchematic(QString &s) +{ + //int const N_R=4; // number of resisitors in 2-order Sallen-Key stage + //int const N_C=2; // number of capacitors in 2-order Sallen-Key stage + RC_elements stage; + int dx = 0; + int N2ord = Nfil/2; // number of 2-nd order stages + int N1stOrd = Nfil%2; // number of 1-st order stages + + s += "\n"; + s += "\n"; + s += QString("<.AC AC1 1 300 440 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); + s += "<.DC DC1 1 60 440 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; + s += "\n"; + s += QString("\n").arg(70+dx); + s += QString("\n").arg(70+dx); + for (int i=1; i<=N2ord; i++) { + stage = Stages.at(i-1); + qDebug()<\n").arg(200+dx); + s += QString("\n").arg(360+dx); + s += QString("\n").arg(1+(i-1)*Nop1).arg(390+dx); + s += QString("\n").arg(2+(i-1)*Nc1).arg(200+dx).arg(C2,0,'f',3).arg(suffix2); + s += QString("\n").arg(1+(i-1)*Nc1).arg(320+dx).arg(C1,0,'f',3).arg(suffix1); + s += QString("\n").arg(1+(i-1)*Nr1).arg(200+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(2+(i-1)*Nr1).arg(150+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(3+(i-1)*Nr1).arg(250+dx).arg(stage.R3,0,'f',3); + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderComponentsLPF(s,Stages.last(),dx+10); + } + + s += "\n"; + s += "\n"; + dx = 0; + s += "<70 250 120 250 \"in\" 120 220 22 \"\">\n"; + s += "<70 250 70 300 \"\" 0 0 0 \"\">\n"; + for (int i=1; i<=N2ord; i++) { + if (i!=1) { + s += QString("<%1 250 %2 270 \"\" 0 0 0 \"\">\n").arg(120+dx).arg(120+dx); + s += QString("<%1 270 %2 270 \"\" 0 0 0 \"\">\n").arg(dx-40).arg(120+dx); + } + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(180+dx).arg(200+dx); + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(220+dx); + s += QString("<%1 210 %2 250 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(200+dx); + s += QString("<%1 250 %2 320 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(200+dx); + s += QString("<%1 290 %2 350 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(360+dx); + s += QString("<%1 130 %2 150 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(200+dx); + s += QString("<%1 130 %2 130 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(320+dx); + s += QString("<%1 130 %2 150 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(280+dx).arg(320+dx); + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(360+dx); + s += QString("<%1 210 %2 250 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + s += QString("<%1 130 %2 130 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(470+dx); + s += QString("<%1 270 %2 270 \"\" 0 0 0 \"\">\n").arg(430+dx).arg(470+dx); + if ((2*i)==Nfil) { + s += QString("<%1 130 %2 270 \"out\" %3 170 70 \"\">\n").arg(470+dx).arg(470+dx).arg(500+dx); + } else { + s += QString("<%1 130 %2 270 \"\" 0 0 0 \"\">\n").arg(470+dx).arg(470+dx); + } + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderWires(s,dx+10); + } + + s += "\n"; +} + +void MFBfilter::createHighPassSchematic(QString &s) { } void MFBfilter::calcHighPass() { + float R1,R2,C1,C2; + float Wc = 2*M_PI*Fc; + + for (int k=1; k <= Nfil/2; k++) { + float re = Poles.at(k-1).real(); + float im = Poles.at(k-1).imag(); + float B = -2.0*re; + float C = re*re + im*im; + + qDebug()<calcFirstOrder(); } @@ -31,7 +147,7 @@ void MFBfilter::calcLowPass() qDebug()<calcFirstOrder(); } diff --git a/mfbfilter.h b/mfbfilter.h index b0f5fffa3b..945375b46d 100644 --- a/mfbfilter.h +++ b/mfbfilter.h @@ -7,15 +7,15 @@ class MFBfilter : public Filter { -private: +protected: void calcHighPass(); void calcLowPass(); + void createHighPassSchematic(QString &s); + void createLowPassSchematic(QString &s); public: MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); - void createSchematic(QString &s); - }; #endif // MFBFILTER_H diff --git a/sallenkey.cpp b/sallenkey.cpp index 65ce937004..37c2f928db 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -9,24 +9,6 @@ SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, Nop1 = 1; } -void SallenKey::createSchematic(QString &s) -{ - switch (ftype) { - case Filter::HighPass : createHighPassSchematic(s); - break; - case Filter::LowPass : createLowPassSchematic(s); - break; - default: break; - } - - QFile sch("filter.sch"); - sch.open(QFile::WriteOnly); - QTextStream out(&sch); - out< > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); - void createSchematic(QString &s); + //void createSchematic(QString &s); }; From cf238b7a69bec8bd86459ec15822d08c6bae9f90 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 27 Apr 2014 17:06:54 +0400 Subject: [PATCH 26/90] Implemented high pass MFB filter schematic generation --- mfbfilter.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/mfbfilter.cpp b/mfbfilter.cpp index 7cd0573cda..0ab3f39c46 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -98,7 +98,75 @@ void MFBfilter::createLowPassSchematic(QString &s) void MFBfilter::createHighPassSchematic(QString &s) { + RC_elements stage; + int dx = 0; + int N2ord = Nfil/2; // number of 2-nd order stages + int N1stOrd = Nfil%2; // number of 1-st order stages + + s += "\n"; + s += "\n"; + s += QString("<.AC AC1 1 300 440 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"%1 kHz\" 1 \"501\" 1 \"no\" 0>\n").arg((10.0*Fc)/1000.0); + s += "<.DC DC1 1 60 440 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; + s += "\n"; + s += QString("\n").arg(70+dx); + s += QString("\n").arg(70+dx); + for (int i=1; i<=N2ord; i++) { + stage = Stages.at(i-1); + qDebug()<\n").arg(200+dx); + s += QString("\n").arg(360+dx); + s += QString("\n").arg(1+(i-1)*Nop1).arg(390+dx); + s += QString("\n").arg(1+(i-1)*Nc1).arg(200+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(2+(i-1)*Nc1).arg(320+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(1+(i-1)*Nc1).arg(200+dx).arg(C1,0,'f',3).arg(suffix1); + s += QString("\n").arg(2+(i-1)*Nc1).arg(150+dx).arg(C2,0,'f',3).arg(suffix2); + s += QString("\n").arg(3+(i-1)*Nc1).arg(250+dx).arg(C1,0,'f',3).arg(suffix1); + dx += 510; + } + + if (N1stOrd!=0) { + createFirstOrderComponentsHPF(s,Stages.last(),dx+10); + } + + s += "\n"; + s += "\n"; + dx = 0; + s += "<70 250 120 250 \"in\" 120 220 22 \"\">\n"; + s += "<70 250 70 300 \"\" 0 0 0 \"\">\n"; + for (int i=1; i<=N2ord; i++) { + if (i!=1) { + s += QString("<%1 250 %2 270 \"\" 0 0 0 \"\">\n").arg(120+dx).arg(120+dx); + s += QString("<%1 270 %2 270 \"\" 0 0 0 \"\">\n").arg(dx-40).arg(120+dx); + } + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(180+dx).arg(200+dx); + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(220+dx); + s += QString("<%1 210 %2 250 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(200+dx); + s += QString("<%1 250 %2 320 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(200+dx); + s += QString("<%1 290 %2 350 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(360+dx); + s += QString("<%1 130 %2 150 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(200+dx); + s += QString("<%1 130 %2 130 \"\" 0 0 0 \"\">\n").arg(200+dx).arg(320+dx); + s += QString("<%1 130 %2 150 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(280+dx).arg(320+dx); + s += QString("<%1 250 %2 250 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(360+dx); + s += QString("<%1 210 %2 250 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); + s += QString("<%1 130 %2 130 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(470+dx); + s += QString("<%1 270 %2 270 \"\" 0 0 0 \"\">\n").arg(430+dx).arg(470+dx); + if ((2*i)==Nfil) { + s += QString("<%1 130 %2 270 \"out\" %3 170 70 \"\">\n").arg(470+dx).arg(470+dx).arg(500+dx); + } else { + s += QString("<%1 130 %2 270 \"\" 0 0 0 \"\">\n").arg(470+dx).arg(470+dx); + } + dx += 510; + } + if (N1stOrd!=0) { + createFirstOrderWires(s,dx+10); + } + + s += "\n"; } void MFBfilter::calcHighPass() @@ -116,8 +184,8 @@ void MFBfilter::calcHighPass() C1 = 10.0/Fc; C2 = C1/Kv; - R1 = B*(2*C1+C2)*Wc; - R2 = (2*C1 + C2)*C/B*C1*C2*Wc; + R1 = B/((2*C1+C2)*Wc); + R2 = ((2*C1 + C2)*C)/(B*C1*C2*Wc); RC_elements curr_stage; curr_stage.N = k; From 8b3edc0d3a89da2f42cc4b8dc8d2295ec659a546 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 28 Apr 2014 19:36:30 +0400 Subject: [PATCH 27/90] Filter poles and zeros calculetion moved to filter.cpp --- filter.cpp | 76 +++++++++++++++++++++++++++-- filter.h | 20 +++++++- filtersintez.cpp | 122 ++++++++++++----------------------------------- mfbfilter.cpp | 4 +- mfbfilter.h | 2 +- sallenkey.cpp | 4 +- sallenkey.h | 2 +- 7 files changed, 125 insertions(+), 105 deletions(-) diff --git a/filter.cpp b/filter.cpp index 0e1ba9bec2..e31d74dac1 100644 --- a/filter.cpp +++ b/filter.cpp @@ -1,12 +1,15 @@ #include "filter.h" -Filter::Filter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) +Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) { - Poles = poles_; - Nfil = Poles.count(); + ffunc = ffunc_; ftype = type_; - Fc = Fcutoff; - Kv = Kv_; + Fc = par.Fc; + Fs = par.Fs; + Rp = par.Rp; + As = par.As; + Ap = par.Ap; + Kv = par.Kv; } Filter::~Filter() @@ -44,6 +47,16 @@ void Filter::createLowPassSchematic(QString &s) void Filter::calcFilter() { Stages.clear(); + Poles.clear(); + Zeros.clear(); + + switch (ffunc) { + case Filter::Chebyshev : calcChebyshev(); + break; + case Filter::Butterworth : calcButterworth(); + break; + default : break; + } switch (ftype) { case Filter::LowPass : calcLowPass(); @@ -119,6 +132,15 @@ void Filter::createPartList(QStringList &lst) } } +void Filter::createPolesZerosList(QStringList &lst) +{ + lst<<""< pole; + foreach(pole,Poles) { + lst< pol(re,im); + Poles.append(pol); + } + + Nfil = Poles.count(); +} + +void Filter::calcButterworth() +{ + float C1=(pow(10,(0.1*Ap))-1)/(pow(10,(0.1*As))-1); + float J2=log10(C1)/(2*log10(Fc/Fs)); + int N2 = round(J2+1); + + Poles.clear(); + Zeros.clear(); + + for (int k=1;k<=N2;k++) { + float re =-1*sin(M_PI*(2*k-1)/(2*N2)); + float im =cos(M_PI*(2*k-1)/(2*N2)); + std::complex pol(re,im); + Poles.append(pol); + } + + Nfil = Poles.count(); +} diff --git a/filter.h b/filter.h index 6becebfa7e..9888638af9 100644 --- a/filter.h +++ b/filter.h @@ -15,11 +15,21 @@ struct RC_elements { float C2; }; +struct FilterParam { + float Ap; + float As; + float Fc; + float Fs; + float Rp; + float Kv; +}; + class Filter { public: enum FType {HighPass, LowPass, BandPass}; + enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev}; protected: QVector< std::complex > Poles; @@ -27,12 +37,17 @@ class Filter QVector Stages; Filter::FType ftype; + Filter::FilterFunc ffunc; int Nfil; - float Fc,Kv; + float Fc,Kv,Fs,Ap,As,Rp; int Nr,Nc,Nopamp; // total number of R,C, opamp int Nr1,Nc1,Nop1; // number of R,C, opamp per stage + void calcButterworth(); + void calcChebyshev(); + void calcCauer(); + void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx); void createFirstOrderWires(QString &s, int dx); @@ -45,12 +60,13 @@ class Filter public: - Filter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); + Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par); virtual ~Filter(); void calcFirstOrder(); void createPartList(QStringList &lst); + void createPolesZerosList(QStringList &lst); virtual void createSchematic(QString &s); diff --git a/filtersintez.cpp b/filtersintez.cpp index e50fb225e0..9c8b4054e6 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -134,7 +134,8 @@ FilterSintez::~FilterSintez() void FilterSintez::slotCalcFilter() { - switch (cbxFilterFunc->currentIndex()) { + + /* switch (cbxFilterFunc->currentIndex()) { case 0 : Nfil = calcButterworth(); break; case 1 : Nfil = calcChebyshev(); @@ -144,7 +145,7 @@ void FilterSintez::slotCalcFilter() case 3 : Nfil = calcElliptic(); break; default: break; - } + }*/ //calcButterworth(); } @@ -152,7 +153,29 @@ void FilterSintez::slotCalcFilter() void FilterSintez::slotCalcSchematic() { - slotCalcFilter(); + FilterParam par; + par.Ap = edtA1->text().toFloat(); + par.As = edtA2->text().toFloat(); + par.Rp = edtPassbRpl->text().toFloat(); + par.Fc = edtF1->text().toFloat(); + par.Fs = edtF2->text().toFloat(); + float G = edtKv->text().toFloat(); + par.Kv = pow(10,G/20.0); + + QStringList lst; + Filter::FilterFunc ffunc; + + switch (cbxFilterFunc->currentIndex()) { + case 0 : ffunc = Filter::Butterworth; + break; + case 1 : ffunc = Filter::Chebyshev; + break; + case 2 : ffunc = Filter::InvChebyshev; + break; + case 3 : ffunc = Filter::Cauer; + break; + default: break; + } Filter::FType ftyp; if (btnHighPass->isChecked()) { @@ -161,10 +184,7 @@ void FilterSintez::slotCalcSchematic() ftyp = Filter::LowPass; } - QStringList lst; - float G = edtKv->text().toFloat(); - float Kv = pow(10,G/20.0); switch (cbxFilterType->currentIndex()) { case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); @@ -172,8 +192,9 @@ void FilterSintez::slotCalcSchematic() break; case 1 : { QString s; - MFBfilter mfb(Poles,ftyp,Fc,Kv); + MFBfilter mfb(ffunc,ftyp,par); mfb.calcFilter(); + mfb.createPolesZerosList(lst); mfb.createPartList(lst); mfb.createSchematic(s); txtResult->setText(lst.join("\n")); @@ -181,8 +202,9 @@ void FilterSintez::slotCalcSchematic() break; case 2 : { QString s; - SallenKey sk(Poles,ftyp,Fc,Kv); + SallenKey sk(ffunc,ftyp,par); sk.calcFilter(); + sk.createPolesZerosList(lst); sk.createPartList(lst); sk.createSchematic(s); txtResult->setText(lst.join("\n")); @@ -215,90 +237,6 @@ void FilterSintez::slotUpdateSchematic() sch_pic->setPixmap(pix); } -int FilterSintez::calcChebyshev() -{ - float alpha = edtPassbRpl->text().toFloat(); - float A2 = edtA2->text().toFloat(); - float F1 = edtF1->text().toFloat(); - float F2 = edtF2->text().toFloat(); - Fc = F1; - - float eps=sqrt(pow(10,0.1*alpha)-1); - - float N1 = acosh(sqrt((pow(10,0.1*A2)-1)/(eps*eps)))/acosh(F2/F1); - int N = ceil(N1); - - QStringList lst; - lst< pol(re,im); - Poles.append(pol); - lst<setText(lst.join("\n")); - return N; -} - -int FilterSintez::calcButterworth() -{ - //float R1,l,w,q,Wc,C5,K7; - - float A1 = edtA1->text().toFloat(); - float A2 = edtA2->text().toFloat(); - float F1 = edtF1->text().toFloat(); - float F2 = edtF2->text().toFloat(); - Fc = F1; - - float K1 = pow(10,(0.1*A1)); - float K2 = pow(10,(0.1*A2)); - float C1=(K1-1)/(K2-1); - float J2=log10(C1)/(2*log10(F1/F2)); - int N2 = round(J2+1); - - QStringList lst; - lst< pol(re,im); - Poles.append(pol); - lst<setText(lst.join("\n")); - - return N2; -} int FilterSintez::calcInvChebyshev() { diff --git a/mfbfilter.cpp b/mfbfilter.cpp index 0ab3f39c46..f3a55f5d89 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -1,7 +1,7 @@ #include "mfbfilter.h" -MFBfilter::MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) - : Filter(poles_,type_,Fcutoff,Kv_) +MFBfilter::MFBfilter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) + : Filter(ffunc_,type_,par) { switch (ftype) { case Filter::LowPass : diff --git a/mfbfilter.h b/mfbfilter.h index 945375b46d..1130398117 100644 --- a/mfbfilter.h +++ b/mfbfilter.h @@ -14,7 +14,7 @@ class MFBfilter : public Filter void createLowPassSchematic(QString &s); public: - MFBfilter(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); + MFBfilter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par); }; diff --git a/sallenkey.cpp b/sallenkey.cpp index 37c2f928db..ce0434848d 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -1,8 +1,8 @@ #include "sallenkey.h" #include -SallenKey::SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_) : - Filter(poles_, type_, Fcutoff, Kv_) +SallenKey::SallenKey(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) : + Filter(ffunc_, type_, par) { Nr1 = 4; Nc1 = 2; diff --git a/sallenkey.h b/sallenkey.h index eff42d2740..fe59f3c3c7 100644 --- a/sallenkey.h +++ b/sallenkey.h @@ -18,7 +18,7 @@ class SallenKey : public Filter void createLowPassSchematic(QString &s); public: - SallenKey(QVector< std::complex > poles_, Filter::FType type_, float Fcutoff, float Kv_=1.0); + SallenKey(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par); //void createSchematic(QString &s); From 29868bb469f54b8a7848598ac5688d8d719ce6aa Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 29 Apr 2014 14:08:28 +0400 Subject: [PATCH 28/90] Corrected first-order stage connection for MFB filter --- .gitignore | 2 ++ filter.cpp | 25 +++++++++++++++---------- filter.h | 2 +- filtersintez.cpp | 6 +++--- mfbfilter.cpp | 4 ++-- sallenkey.cpp | 27 ++++++++++++++++----------- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 5003808d95..f3d7261b8f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ Makefile moc_*.cpp *.sch *.sch~ +*.dat +*.dpl diff --git a/filter.cpp b/filter.cpp index e31d74dac1..576d3b9bb3 100644 --- a/filter.cpp +++ b/filter.cpp @@ -9,7 +9,7 @@ Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) Rp = par.Rp; As = par.As; Ap = par.Ap; - Kv = par.Kv; + Kv = par.Kv; // gain of 1 stage } Filter::~Filter() @@ -103,7 +103,7 @@ void Filter::calcFirstOrder() R2 = Kv*R1/(Kv - 1); R3 = Kv*R1; } else { - R2 = 999; + R2 = 1.0; R3 = 0; } RC_elements curr_stage; @@ -122,23 +122,28 @@ void Filter::calcFirstOrder() void Filter::createPartList(QStringList &lst) { - lst<<"N C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; + lst< pole; foreach(pole,Poles) { lst<\n").arg(Nc+1).arg(170+dx).arg(C1,0,'f',3).arg(suf); } -void Filter::createFirstOrderWires(QString &s, int dx) +void Filter::createFirstOrderWires(QString &s, int dx, int y) { s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(70+dx); - s += QString("<%1 190 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20); - s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); + s += QString("<%1 190 %2 %3 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-20).arg(y); + s += QString("<%1 %2 %3 %4 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(y).arg(dx-50).arg(y); s += QString("<%1 190 %2 190 \"\" 0 0 0 \"\">\n").arg(130+dx).arg(170+dx); s += QString("<%1 160 %2 160 \"out\" %3 130 39 \"\">\n").arg(310+dx).arg(360+dx).arg(380+dx); diff --git a/filter.h b/filter.h index 9888638af9..5a7377f812 100644 --- a/filter.h +++ b/filter.h @@ -50,7 +50,7 @@ class Filter void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx); - void createFirstOrderWires(QString &s, int dx); + void createFirstOrderWires(QString &s, int dx, int y); float autoscaleCapacitor(float C, QString &suffix); virtual void calcHighPass(); virtual void calcLowPass(); diff --git a/filtersintez.cpp b/filtersintez.cpp index 9c8b4054e6..4cb2f880a6 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -13,8 +13,8 @@ FilterSintez::FilterSintez(QWidget *parent) QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); lblInputData = new QLabel(tr("Входные данные")); - lblA1 = new QLabel(tr("Затухание фильтра в полосе пропускания, Ap")); - lblA2 = new QLabel(tr("Минимальное затухание фильтра в полосе задерживания, As")); + lblA1 = new QLabel(tr("Затухание в полосе пропускания, Ap")); + lblA2 = new QLabel(tr("Мин. затухание в полосе задерживания, As")); lblF1 = new QLabel(tr("Частота среза фильтра, Fc (Гц)")); lblF2 = new QLabel(tr("Начало полосы задерживания, Fs (Гц)")); lblRpl1 = new QLabel(tr("Амплитуда пульсаций в полосе пропускания Rp(дБ)")); @@ -106,6 +106,7 @@ FilterSintez::FilterSintez(QWidget *parent) center->addWidget(lblResult); center->addWidget(txtResult); + txtResult->setMinimumWidth(400); left->addWidget(lblSch); left->addWidget(btnLowPass); @@ -147,7 +148,6 @@ void FilterSintez::slotCalcFilter() default: break; }*/ - //calcButterworth(); } void FilterSintez::slotCalcSchematic() diff --git a/mfbfilter.cpp b/mfbfilter.cpp index f3a55f5d89..afa795ff80 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -90,7 +90,7 @@ void MFBfilter::createLowPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderWires(s,dx+10); + createFirstOrderWires(s,dx+10,270); } s += "\n"; @@ -163,7 +163,7 @@ void MFBfilter::createHighPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderWires(s,dx+10); + createFirstOrderWires(s,dx+10,270); } s += "\n"; diff --git a/sallenkey.cpp b/sallenkey.cpp index ce0434848d..734401098e 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -14,6 +14,9 @@ void SallenKey::calcLowPass() { float R1,R2,R3,R4,C1,C2; float Wc = 2*M_PI*Fc; + float Nst = Nfil/2 + Nfil%2; + float Kv1 = pow(Kv,1.0/Nst); + qDebug()< Date: Tue, 29 Apr 2014 14:48:52 +0400 Subject: [PATCH 29/90] Removed CalcFilterFunction pushbutton --- filtersintez.cpp | 129 +---------------------------------------------- filtersintez.h | 7 --- 2 files changed, 1 insertion(+), 135 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 4cb2f880a6..b7cb2bcf66 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -46,8 +46,6 @@ FilterSintez::FilterSintez(QWidget *parent) <addItems(lst2); - btnCalcFiltFunc = new QPushButton(tr("Рассчитать функцию фильтра")); - connect(btnCalcFiltFunc,SIGNAL(clicked()),this,SLOT(slotCalcFilter())); btnCalcSchematic = new QPushButton(tr("Рассчитать элементы схемы фильтра")); connect(btnCalcSchematic,SIGNAL(clicked()),SLOT(slotCalcSchematic())); @@ -68,7 +66,7 @@ FilterSintez::FilterSintez(QWidget *parent) QStringList lst; lst<addItems(lst); connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); @@ -96,8 +94,6 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(edtF2); left->addWidget(lblRpl1); left->addWidget(edtPassbRpl); - //left->addWidget(lblRpl2); - //left->addWidget(edtStopbRpl); left->addWidget(lblKv); left->addWidget(edtKv); left->addWidget(lblTyp); @@ -112,7 +108,6 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(btnLowPass); left->addWidget(btnHighPass); left->addWidget(cbxFilterType); - left->addWidget(btnCalcFiltFunc); left->addWidget(btnCalcSchematic); right->addWidget(imgAFR); @@ -133,23 +128,6 @@ FilterSintez::~FilterSintez() } -void FilterSintez::slotCalcFilter() -{ - - /* switch (cbxFilterFunc->currentIndex()) { - case 0 : Nfil = calcButterworth(); - break; - case 1 : Nfil = calcChebyshev(); - break; - case 2 : Nfil = calcInvChebyshev(); - break; - case 3 : Nfil = calcElliptic(); - break; - default: break; - }*/ - -} - void FilterSintez::slotCalcSchematic() { @@ -238,99 +216,6 @@ void FilterSintez::slotUpdateSchematic() } -int FilterSintez::calcInvChebyshev() -{ - float A1 = edtA1->text().toFloat(); - float A2 = edtA2->text().toFloat(); - float F1 = edtF1->text().toFloat(); - float F2 = edtF2->text().toFloat(); - Fc = F1; - - float W5=F2/F1; - float K4=pow(10,(0.1*A1)); - float C5=pow((K4-1),0.5); - - float J5 = log(C5+pow((C5*C5-1),0.5))/log(W5+pow((W5*W5-1),0.5)); - int N5 = round(J5+1); - - QStringList lst; - - lst<setText(lst.join("\n")); - - return N5; -} - -int FilterSintez::calcElliptic() -{ - float A1 = edtA1->text().toFloat(); - float A2 = edtA2->text().toFloat(); - float F1 = edtF1->text().toFloat(); - float F2 = edtF2->text().toFloat(); - Fc = F1; - - float W5=F2/F1; - float K9=F1/F2; - float K4=pow(10,(0.1*A1)); - float K1=pow((1-K9*K9),0.5); - - float J0=A2+12.16-20*log10(pow((K4-1),0.5)); - float J9=6.08+20*log10((1+pow(K1,0.5))/(1-pow(K1,0.5))); - float J7=J0/J9; - int N7=round(J7+1); - - QStringList lst; - lst<setText(lst.join("\n")); - - return N7; -} - void FilterSintez::calcDblQuadHPF() { @@ -341,18 +226,6 @@ void FilterSintez::calcDblQuadLPF() } -void FilterSintez::calcMultiloopHPF() -{ - -} - -void FilterSintez::calcMultiloopLPF() -{ - -} - - - void FilterSintez::calcPassive() { diff --git a/filtersintez.h b/filtersintez.h index 5706d247e7..f05abdba0c 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -30,7 +30,6 @@ class FilterSintez : public QMainWindow QLineEdit *edtStopbRpl; QComboBox *cbxFilterFunc; - QPushButton *btnCalcFiltFunc; QPushButton *btnCalcSchematic; QLabel *lblResult; @@ -56,11 +55,6 @@ class FilterSintez : public QMainWindow QWidget *zenter; - int calcChebyshev(); - int calcButterworth(); - int calcInvChebyshev(); - int calcElliptic(); - void calcDblQuadLPF(); void calcDblQuadHPF(); void calcMultiloopLPF(); @@ -80,7 +74,6 @@ class FilterSintez : public QMainWindow private slots: - void slotCalcFilter(); void slotUpdateSchematic(); void slotCalcSchematic(); From d1c562bc93ab2b7caf12b1b52ca27f337e65d990 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 30 Apr 2014 13:44:03 +0400 Subject: [PATCH 30/90] Added polynoms mathemathics for future filter classes --- QFilterSintez.pro | 7 +- filter.cpp | 14 +- filter.h | 2 +- mfbfilter.cpp | 16 +- qf_matrix.h | 50 ++ qf_poly.cpp | 1580 +++++++++++++++++++++++++++++++++++++++++++++ qf_poly.h | 142 ++++ sallenkey.cpp | 20 +- 8 files changed, 1803 insertions(+), 28 deletions(-) create mode 100644 qf_matrix.h create mode 100644 qf_poly.cpp create mode 100644 qf_poly.h diff --git a/QFilterSintez.pro b/QFilterSintez.pro index f5ae003b2d..76fb7d68d0 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -16,9 +16,12 @@ SOURCES += main.cpp\ filtersintez.cpp \ filter.cpp \ sallenkey.cpp \ - mfbfilter.cpp + mfbfilter.cpp \ + qf_poly.cpp HEADERS += filtersintez.h \ filter.h \ sallenkey.h \ - mfbfilter.h + mfbfilter.h \ + qf_poly.h \ + qf_matrix.h diff --git a/filter.cpp b/filter.cpp index 576d3b9bb3..5e2990e35a 100644 --- a/filter.cpp +++ b/filter.cpp @@ -67,9 +67,9 @@ void Filter::calcFilter() break; } - Nr = Nr1*(Nfil/2); - Nc = Nc1*(Nfil/2); - Nopamp = Nop1*Nfil/2; + Nr = Nr1*(order/2); + Nc = Nc1*(order/2); + Nopamp = Nop1*order/2; } @@ -85,11 +85,11 @@ void Filter::calcLowPass() void Filter::calcFirstOrder() { - if (Nfil%2 != 0) { + if (order%2 != 0) { float R2,R3; - int k = Nfil/2 + 1; + int k = order/2 + 1; float Wc = 2*M_PI*Fc; float re = Poles.at(k-1).real(); //float im = Poles.at(k-1).imag(); @@ -236,7 +236,7 @@ void Filter::calcChebyshev() Poles.append(pol); } - Nfil = Poles.count(); + order = Poles.count(); } void Filter::calcButterworth() @@ -255,5 +255,5 @@ void Filter::calcButterworth() Poles.append(pol); } - Nfil = Poles.count(); + order = Poles.count(); } diff --git a/filter.h b/filter.h index 5a7377f812..ebdb49fe06 100644 --- a/filter.h +++ b/filter.h @@ -38,7 +38,7 @@ class Filter Filter::FType ftype; Filter::FilterFunc ffunc; - int Nfil; + int order; float Fc,Kv,Fs,Ap,As,Rp; int Nr,Nc,Nopamp; // total number of R,C, opamp diff --git a/mfbfilter.cpp b/mfbfilter.cpp index afa795ff80..5b6d594e5c 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -27,8 +27,8 @@ void MFBfilter::createLowPassSchematic(QString &s) //int const N_C=2; // number of capacitors in 2-order Sallen-Key stage RC_elements stage; int dx = 0; - int N2ord = Nfil/2; // number of 2-nd order stages - int N1stOrd = Nfil%2; // number of 1-st order stages + int N2ord = order/2; // number of 2-nd order stages + int N1stOrd = order%2; // number of 1-st order stages s += "\n"; s += "\n"; @@ -81,7 +81,7 @@ void MFBfilter::createLowPassSchematic(QString &s) s += QString("<%1 210 %2 250 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); s += QString("<%1 130 %2 130 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(470+dx); s += QString("<%1 270 %2 270 \"\" 0 0 0 \"\">\n").arg(430+dx).arg(470+dx); - if ((2*i)==Nfil) { + if ((2*i)==order) { s += QString("<%1 130 %2 270 \"out\" %3 170 70 \"\">\n").arg(470+dx).arg(470+dx).arg(500+dx); } else { s += QString("<%1 130 %2 270 \"\" 0 0 0 \"\">\n").arg(470+dx).arg(470+dx); @@ -100,8 +100,8 @@ void MFBfilter::createHighPassSchematic(QString &s) { RC_elements stage; int dx = 0; - int N2ord = Nfil/2; // number of 2-nd order stages - int N1stOrd = Nfil%2; // number of 1-st order stages + int N2ord = order/2; // number of 2-nd order stages + int N1stOrd = order%2; // number of 1-st order stages s += "\n"; s += "\n"; @@ -154,7 +154,7 @@ void MFBfilter::createHighPassSchematic(QString &s) s += QString("<%1 210 %2 250 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(320+dx); s += QString("<%1 130 %2 130 \"\" 0 0 0 \"\">\n").arg(320+dx).arg(470+dx); s += QString("<%1 270 %2 270 \"\" 0 0 0 \"\">\n").arg(430+dx).arg(470+dx); - if ((2*i)==Nfil) { + if ((2*i)==order) { s += QString("<%1 130 %2 270 \"out\" %3 170 70 \"\">\n").arg(470+dx).arg(470+dx).arg(500+dx); } else { s += QString("<%1 130 %2 270 \"\" 0 0 0 \"\">\n").arg(470+dx).arg(470+dx); @@ -174,7 +174,7 @@ void MFBfilter::calcHighPass() float R1,R2,C1,C2; float Wc = 2*M_PI*Fc; - for (int k=1; k <= Nfil/2; k++) { + for (int k=1; k <= order/2; k++) { float re = Poles.at(k-1).real(); float im = Poles.at(k-1).imag(); float B = -2.0*re; @@ -207,7 +207,7 @@ void MFBfilter::calcLowPass() float R1,R2,R3,C1,C2; float Wc = 2*M_PI*Fc; - for (int k=1; k <= Nfil/2; k++) { + for (int k=1; k <= order/2; k++) { float re = Poles.at(k-1).real(); float im = Poles.at(k-1).imag(); float B = -2.0*re; diff --git a/qf_matrix.h b/qf_matrix.h new file mode 100644 index 0000000000..0b4a3f87a4 --- /dev/null +++ b/qf_matrix.h @@ -0,0 +1,50 @@ +/*************************************************************************** + qf_matrix.h + ---------------- + begin : Mon Jan 02 2006 + copyright : (C) 2006 by Stefan Jahn + email : stefan@lkcc.org + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _QF_MATRIX_H +#define _QF_MATRIX_H + +class qf_matrix +{ + public: + // constructor + qf_matrix (unsigned int d) { + data = (qf_double_t *) calloc (d * d, sizeof (qf_double_t)); + n = d; + } + + // destructor + ~qf_matrix () { + free (data); + } + + // accessor operators + qf_double_t operator () (int r, int c) const { + return data[r * n + c]; + } + qf_double_t & operator () (int r, int c) { + return data[r * n + c]; + } + + // size of matrix + unsigned int n; + + private: + qf_double_t * data; +}; + +#endif // _QF_MATRIX_H diff --git a/qf_poly.cpp b/qf_poly.cpp new file mode 100644 index 0000000000..80705da079 --- /dev/null +++ b/qf_poly.cpp @@ -0,0 +1,1580 @@ +/*************************************************************************** + qf_poly.cpp + ---------------- + begin : Mon Jan 02 2006 + copyright : (C) 2006 by Vincent Habchi, F5RCS + email : 10.50@free.fr + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// Class for polynoms with real coefficients (R[X]) +// Basic operations are covered +// It includes also an algorithm to find all the roots of a real +// polynom. + +#include +#include +#include +#include + +#undef _QF_POLY_DEBUG + +#include "qf_poly.h" + +// A polynom is essentially a structure with an order (max. index) +// and a table storing coefficients +qf_poly::qf_poly () : + rep (NONE), d (0), krts (0), p (NULL), rts (NULL) { +} + +// Creates default polynoms +qf_poly::qf_poly (unsigned o) : + rep (NONE), d (o), krts (0), p (NULL), rts (NULL) { +} + +// This function creates irreductible real polynoms +// That is either constants, monoms, or binoms +qf_poly::qf_poly (qf_double_t a, qf_double_t b, qf_double_t c, unsigned deg) { + +#ifdef _QF_POLY_DEBUG + std::cout << "qf_poly (ax^2+bx+c), a = " << a << ", b = " << b + << ", c = " << c << ", d = " << deg << "\n"; +#endif + + // Pathological cases + if ((deg == 2) && (a == 0)) { + deg = 1; + a = b; + b = c; + } + if ((deg == 1) && (a == 0)) { + deg = 0; + a = b; + } + + // Proceed with normal cases + switch (deg) { + case 0: + // Constant + d = 0; + p = new qf_double_t[1]; + p[0] = a; + rts = NULL; // no root (or an infinite #of them) + krts = a; + rep = BOTH; + break; + case 1: + // (aX + b) + d = 1; + p = new qf_double_t[2]; + p[0] = b; + p[1] = a; + rts = new qf_double_t[2]; + rts[0] = ROUND_ROOT (-b / a); + rts[1] = 0; + krts = a; + rep = BOTH; + break; + default: + // Polynom of d 2 (aX^2 + bX + c) + if (deg > 2) + std::cout << "Warning: qf_poly called with deg > 2.\n"; + d = 2; + p = new qf_double_t[3]; + p[0] = c; + p[1] = b; + p[2] = a; + rts = new qf_double_t[4]; + krts = a; + qf_double_t dlt = (b * b - 4 * a * c); + if (dlt == 0) { + // Double root (should not occur) + rts[0] = rts[2] = ROUND_ROOT (-b / (2 * a)); + rts[1] = rts[3] = 0; + } else if (dlt > 0) { + // Two real roots (should not occur) + rts[1] = rts[3] = 0; + rts[0] = ROUND_ROOT ((-b + sqrt (dlt)) / (2 * a)); + rts[2] = ROUND_ROOT (-(b + sqrt (dlt)) / (2 * a)); + } else { + // Two conjugate complex root (normal case) + rts[0] = rts[2] = ROUND_ROOT (-b / (2 * a)); + rts[1] = ROUND_ROOT (sqrt (-dlt) / (2 * a)); + rts[3] = -rts[1]; + } + rep = BOTH; + break; + } + +#ifdef _QF_POLY_DEBUG + std::cout << "qf_poly ax^2+bx+c: "; + this->disp ("prod"); +#endif +} + +// Creates a polynom and instantiates it out of a constant table +qf_poly::qf_poly (int o, const qf_double_t coef[]) : + rep (COEFF), d (o), krts (0), rts (NULL) { + + p = new qf_double_t[o + 1]; + for (int i = o; i >= 0; i--) p[i] = coef[o - i]; + +#ifdef _QF_POLY_DEBUG + std::cout << "qf_poly coeffs: "; + this->disp ("P"); +#endif + return; +} + +// Creates a polynom out of its roots and a constant factor +// The roots are complex numbers +// If a root is complex, then its conjugate is also a root +// since the coefficients are real. +qf_poly::qf_poly (int o, qf_double_t k, const qf_double_t r[]) : + rep (ROOTS), d (o), p (NULL) { + + rts = new qf_double_t[2 * o]; + for (int i = 0; i < 2 * o; i++) + rts[i] = ROUND_ROOT (r[i]); + krts = k; + +#ifdef _QF_POLY_DEBUG + std::cout << "qf_poly (roots): "; + this->disp ("P"); +#endif + return; +} + +// Copy constructor +qf_poly::qf_poly (const qf_poly & P) : + rep (P.rep), d (P.d), krts (0), p (NULL), rts (NULL) { + + if (rep & COEFF) { + p = new qf_double_t[d + 1]; + memcpy (p, P.p, sizeof (qf_double_t) * (d + 1)); + } + if (rep & ROOTS) { + rts = new qf_double_t[2 * d]; + memcpy (rts, P.rts, sizeof (qf_double_t) * 2 * d); + krts = P.krts; + } +} + +// Assignment operator +// Identical to previous +qf_poly & qf_poly::operator = (const qf_poly & P) { + if (&P == this) // Self copy, nothing to do + return (*this); + + d = P.d; + rep = P.rep; + + if (p != NULL) delete[] p; + if (rts != NULL) delete[] rts; + p = rts = NULL; + krts = 0; + + if (rep & COEFF) { + p = new qf_double_t[d + 1]; + memcpy (p, P.p, sizeof (qf_double_t) * (d + 1)); + } + if (rep & ROOTS) { + rts = new qf_double_t[2 * d]; + memcpy (rts, P.rts, sizeof (qf_double_t) * (2 * d)); + krts = P.krts; + } + return (*this); +} + +// Garbage bin +qf_poly::~qf_poly () { + if (p != NULL) delete[] p; + if (rts != NULL) delete[] rts; +} + +// Basic functions. + +// Access to the element of nth order +// [] overload +qf_double_t & qf_poly::operator [] (int i) { + if (rep == NONE) { + std::cout << "qf_poly::[] used on a NONE polynom.\n"; + exit (-1); + } + if (rep & COEFF) + return p[i]; + return rts[i]; +} + +// Returns d (order) of polynom +unsigned qf_poly::deg () { + return d; +} + +qf_double_t qf_poly::k () { + if (rep == NONE) { + std::cout << "qf_poly::k () used on a NONE polynom.\n"; + exit (-1); + } + if (rep & ROOTS) + return krts; + return p[d]; +} + +// Simplifies a polynom +// This function looks for the highest non-zero term and sets +// d accordingly, so that we do not perform useless operations on 0s +// Note that the unused 0s are not freed. We cannot do that at that +// time without copying, which is a ** overhead +// Useful after additions +void qf_poly::spl () { + int i = d; + + if (rep == NONE) { + std::cout << "qf_poly::spl () used on a NONE polynom.\n"; + exit (-1); + } + + if (d == 0) + return; + + if (rep == ROOTS) + return; + + // We scan from highest to lowest order + while (i > 0) { + if (p[i] == 0) + i--; + else + break; + } + d = i; + + return; +} + +// Arithmetical operations + +// Negates (Unary minus : P -> -P) +qf_poly qf_poly::operator - (void) { + if (rep == NONE) { + std::cout << "qf_poly::unary - used on a NONE polynom.\n"; + exit (-1); + } + + qf_poly R (d); + + if (rep & COEFF) { + R.p = new qf_double_t[d + 1]; + for (unsigned i = 0; i <= d; i++) + R.p[i] = -p[i]; + } + if (rep & ROOTS) { + R.rts = new qf_double_t[2 * d]; + memcpy (R.rts, rts, sizeof (qf_double_t) * 2 * d); + R.krts = -krts; + } + + R.rep = rep; + return R; +} + +// Addition +qf_poly operator + (qf_poly P, qf_poly Q) { + if ((Q.rep == NONE) || (P.rep == NONE)) { + std::cout << "qf_poly::+ used on a NONE polynom.\n"; + exit (-1); + } + + if (Q.d >= P.d) { + qf_poly R (Q); + return R += P; + } + else { + qf_poly R (P); + return R += Q; + } +} + +// Self-Addition +qf_poly qf_poly::operator += (qf_poly P) { + if ((rep == NONE) || (P.rep == NONE)) { + std::cout << "qf_poly::+= used on a NONE polynom.\n"; + exit (-1); + } + + // We cannot add two polynoms if one of them is under the ROOTS form + if (rep == ROOTS) + to_coeff (); + + // We add coefficients, not roots! + if (P.rep == ROOTS) + P.to_coeff (); + + if (d >= P.d) { + for (unsigned i = 0; i <= P.d; i++) + p[i] += P.p[i]; + } + else { + qf_double_t * pp = new qf_double_t[P.d]; + memcpy (pp, P.p, sizeof (qf_double_t) * P.d); + for (unsigned i = 0; i <= d; i++) + pp[i] += p[i]; + delete[] p; + p = pp; + } + + if (rep & ROOTS) { + rep = COEFF; // We must recompute roots if needed + delete[] rts; + rts = NULL; + krts = 0; + } + spl (); // Simplifies + return (*this); +} + +// Substraction +qf_poly operator - (qf_poly P, qf_poly Q) { + if ((P.rep == NONE) || (Q.rep == NONE)) { + std::cout << "qf_poly::- used on a NONE polynom.\n"; + exit (-1); + } + + if (P.d >= Q.d) { + qf_poly R (P); + return R -= Q; + } + else { + qf_poly R (Q); + return R -= P; + } +} + +// Self-Substraction +qf_poly qf_poly::operator -= (qf_poly P) { + if ((rep == NONE) || (P.rep == NONE)) { + std::cout << "qf_poly::-= used on a NONE polynom.\n"; + exit (-1); + } + + if (rep == ROOTS) + to_coeff (); + + if (P.rep == ROOTS) + P.to_coeff (); + + if (d >= P.d) { + for (unsigned i = 0; i <= P.d; i++) + p[i] -= P.p[i]; + } + else { + qf_double_t * pp = new qf_double_t[P.d + 1]; + memcpy (pp, P.p, sizeof (qf_double_t) * (P.d + 1)); + for (unsigned i = 0; i <= P.d; i++) + if (i <= d) + pp[i] = p[i] - pp[i]; + else + pp[i] = -pp[i]; + delete[] p; + p = pp; + } + + if (rep & ROOTS) { + rep = COEFF; // We must recompute roots if needed + delete[] rts; + rts = NULL; + krts = 0; + } + spl (); // Simplifies + return (*this); +} + +// Multiplication of two polynoms +qf_poly operator * (qf_poly P, qf_poly Q) { + if ((P.rep == NONE) || (Q.rep == NONE)) { + std::cout << "qf_poly::* used on a NONE polynom.\n"; + exit (-1); + } + + qf_poly R (P); + R *= Q; + return R; +} + +// Multiplication with a scalar +qf_poly operator * (qf_poly P, const qf_double_t m) { + if (P.rep == NONE) { + std::cout << "qf_poly::* (scalar) used on a NONE polynom.\n"; + exit (-1); + } + + qf_poly R (P); + R *= m; + return R; +} + +// Self-Multiply +qf_poly qf_poly::operator *= (qf_poly P) { + if ((rep == NONE) || (P.rep == NONE)) { + std::cout << "qf_poly::*= () used on a NONE polynom.\n"; + exit (-1); + } + + // Just a constant to multiply + if (P.d < 1) { + if (P.rep & COEFF) + return ((*this) *= P.p[0]); + else + return ((*this) *= P.krts); + } + + // Resizes the coefficient list + if (rep & COEFF) { + if (!(P.rep & COEFF)) P.to_coeff (); + qf_double_t * q = new qf_double_t[d + P.d + 1]; + memset (q, 0, sizeof (qf_double_t) * (d + P.d + 1)); + for (unsigned i = 0; i <= d; i++) + for (unsigned j = 0; j <= P.d; j++) + q[i + j] += p[i] * P.p[j]; + delete[] p; + p = q; + } + + // The roots are the concatenation of the roots of both polynoms + if (rep & ROOTS) { + if (!(P.rep & ROOTS)) P.to_roots (); + qf_double_t * rtsp = new qf_double_t[2 * (d + P.d)]; + memcpy (rtsp, rts, sizeof (qf_double_t) * 2 * d); + memcpy (&rtsp[2 * d], P.rts, sizeof (qf_double_t) * 2 * P.d); + delete[] rts; + rts = rtsp; + krts *= P.krts; + } + + d += P.d; + return (*this); +} + +// Self-Scalar-Multiply +qf_poly qf_poly::operator *= (const qf_double_t m) { + if (rep == NONE) { + std::cout << "qf_poly::*= (scalar) used on a NONE polynom.\n"; + exit (-1); + } + + if (m == 0) { + krts = d = 0; + delete[] rts; + delete[] p; + rts = p = NULL; + rep = COEFF; + return (*this); + } + + if (m == 1) + return (*this); + + if (rep & COEFF) + for (unsigned i = 0; i <= d; i++) + p[i] *= m; + + if (rep & ROOTS) + krts *= m; + + return (*this); +} + +// Test +bool qf_poly::operator == (qf_poly P) { + if (rep == NONE) + return false; + + // Two polynoms can be equal only if their degree is the same + if (d != P.d) + return false; + + // We can't compare two polynoms using the roots, because they can + // be stored in different order, and therefore the comparison would + // be cumbersome. It is shorter to translate the polynoms in COEFF + // form, then make a comparison of each coefficient + + if (rep == ROOTS) + to_coeff (); + + if (P.rep == ROOTS) + P.to_coeff (); + + for (unsigned i = 0; i <= d; i++) + if (p[i] != P.p[i]) + return false; + + return true; +} + +bool qf_poly::operator != (qf_poly P) { + return !((*this) == P); +} + +bool qf_poly::is_null (void) { + if (rep == NONE) { + std::cout << "Warning qf_poly::is_null() on a NONE polynom.\n"; + return true; + } + + if (d == 0) + return true; + + if (d > 1) + return false; + + if (rep & ROOTS) + return (krts == 0); + else + return (p[0] == 0); +} + +// Basic division by x^n == left shift n places +qf_poly qf_poly::operator << (unsigned n) { + if (rep == NONE) { + std::cout << "qf_poly::<< used on a NONE polynom.\n"; + exit (-1); + } + + if (n == 0) + return (*this); + + if (d < n) + return qf_poly (0, 0, 0, 0); // 0 + + else if (d == n) + return qf_poly (p[d], 0, 0, 0); // Q(x) = P(n) + + qf_poly R; + + if (rep & COEFF) { + for (unsigned i = 0; i < n; i++) + if (p[i] != 0) { + std::cout << "Warning: << by " << n << " asked for but only " + << i << " possible.\n"; + n = i; + } + + // Okay, proceed + R.p = new qf_double_t[d - n + 1]; + memcpy (R.p, &(p[n]), sizeof (qf_double_t) * (d - n + 1)); + R.d = d - n; + } + + if (rep & ROOTS) { + int nbz = n; + R.rts = new qf_double_t[2 * d]; + R.krts = krts; + + // Eliminates n zero roots + for (unsigned i = 0, j = 0; i < 2 * d; i += 2) { + if ((rts[i] == 0) && (rts[i + 1] == 0) && (nbz != 0)) + nbz--; + + else { + R.rts[j] = rts[i]; + R.rts[j + 1] = rts[i + 1]; + j += 2; + } + } + + R.d = d - n; + + // We did not found a sufficient number of zeros + if (nbz != 0) { + std::cout << "Warning: << by " << n << " asked for but only " + << n - nbz << " possible.\n"; + R.d += nbz; + } + } + + R.rep = rep; + return R; +} + +// Multiplies by x^n +qf_poly qf_poly::operator >> (unsigned n) { + if (rep == NONE) { + std::cout << "qf_poly::>> used on a NONE polynom.\n"; + exit (-1); + } + + if (n == 0) + return (*this); + + qf_poly R (d + n); + + if (rep & COEFF) { + R.p = new qf_double_t[d + n + 1]; + memset (R.p, 0, sizeof (qf_double_t) * n); + memcpy (&(R.p[n]), p, sizeof (qf_double_t) * (d + 1)); + } + + if (rep & ROOTS) { + R.rts = new qf_double_t[2 * (d + n)]; + memset (R.rts, 0, sizeof (qf_double_t) * 2 * n); // n times root = 0 + memcpy (&(R.rts[2 * n]), rts, sizeof (qf_double_t) * 2 * d); + R.krts = krts; + } + + R.rep = rep; + return R; +} + +// Creates the odd part of a polynom +qf_poly qf_poly::odd () { + qpr orep = rep; + + if (rep == NONE) { + std::cout << "qf_poly::odd () used on a NONE polynom.\n"; + exit (-1); + } + + if (rep == ROOTS) + to_coeff (); + + qf_poly P (*this); + + int i = d; + + if ((i % 2) == 1) + i--; + + for (; i >= 0; i -= 2) + P.p[i] = 0; + + P.spl (); + + if ((orep == ROOTS) || (orep == BOTH)) + P.to_roots (); + + return P; +} + +// Creates the even part of a polynom +qf_poly qf_poly::even () { + qpr orep = rep; + + if (rep == NONE) { + std::cout << "qf_poly::even () used on a NONE polynom.\n"; + exit (-1); + } + + + if (rep == ROOTS) + to_coeff (); + + qf_poly P (*this); + + int i = d; + + if (i == 0) + return P; + + if ((i % 2) == 0) + i--; + + for (; i >= 1; i -= 2) + P.p[i] = 0; + + P.spl (); + + if ((orep == ROOTS) || (orep == BOTH)) + P.to_roots (); + + return P; +} + +// computes P(-X) +qf_poly qf_poly::mnx () { + if (rep == NONE) { + std::cout << "qf_poly::mnx () used on a NONE polynom.\n"; + exit (-1); + } + + qf_poly P (d); + + if ((rep == COEFF) || (rep == BOTH)) { + P.p = new qf_double_t[d + 1]; + for (unsigned i = 0; i <= d; i++) + P.p[i] = ((i % 2) == 0 ? p[i] : -p[i]); + } + + if ((rep == ROOTS) || (rep == BOTH)) { + P.rts = new qf_double_t[2 * d]; + + for (unsigned i = 0; i < 2 * d; i++) + P.rts[i] = -rts[i]; + + P.krts = ((d % 2) == 0 ? krts : -krts); + } + + P.rep = rep; + return P; +} + +// "Half square" : P(X) * P(-X) +qf_poly qf_poly::hsq () { + if (rep == NONE) { + std::cout << "qf_poly::hsq () used on a NONE polynom.\n"; + exit (-1); + } + + qf_poly P (*this); + + P *= mnx (); + + return P; +} + +// Q(X) <- P(X^2) +qf_poly qf_poly::sqr () { + if (rep == NONE) { + std::cout << "qf_poly::sqr () used on a NONE polynom.\n"; + exit (-1); + } + + if (rep == ROOTS) + to_coeff (); + + qf_poly P (even ()); + + // Contains odd order terms + if ((*this) != P) { + std::cout << "Error! qf_poly::sqr () used on a non-square polynom.\n"; + exit (-1); + } + + qf_poly Q (d / 2); + + Q.p = new qf_double_t[d / 2 + 1]; + + for (unsigned i = 0; i <= d / 2; i++) + Q.p[i] = p[2 * i]; + + Q.rep = COEFF; + + if ((rep == BOTH) || (rep == ROOTS)) + Q.to_roots (); + + return Q; // Q(X) = P(X^2) +} + +// Eliminates a prime factor +void qf_poly::div (qf_double_t r, qf_double_t i) { + if (rep == NONE) { + std::cout << "qf_poly::div () used on a NONE polynom.\n"; + exit (-1); + } + + i = fabs (i); // Imaginary part must be > 0 + + // First examins pathological cases + + if (d == 0) { + std::cout << "Warning: Div () called on a constant polynom.\n"; + return; + } + + if ((d == 1) && (i != 0)) { + std::cout << "Div () real/complex error.\n"; + return; + } + + if (d == 1) { + if (((rep == ROOTS) || (rep == BOTH)) + && (fabs (rts[0] - r) < ROOT_TOL) + && (fabs (rts[1]) < ROOT_TOL)) { + d = 0; + delete[] rts; + rts = NULL; + delete[] p; + p = new qf_double_t[1]; + p[0] = krts; + rep = BOTH; + return; + } + + if ((rep == COEFF) && (fabs (p[0] / p[1] + r) < ROOT_TOL)) { + qf_double_t temp = p[1]; + d = 0; + delete[] p; + p = new qf_double_t[1]; + p[0] = temp; + delete[] rts; + krts = temp; + rep = BOTH; + return; + } + + std::cout << "Warning: Div () error. Specified factor not found.\n"; + return; + } + + // Proceed to general case. + // If i = 0, we divide by (X - r) + // If i != 0, we divide by (X^2 - 2rX + r^2+i^2), that is to say + // by (X - (r + iI))(X - (r - iI)) where I^2 = -1 + if (rep == COEFF) + to_roots (); + + qf_double_t * rtsp = new qf_double_t[2 * d]; + + bool found = false; + + for (unsigned k = 0, j = 0; k < 2 * d; k += 2) { +#ifdef _QF_POLY_DEBUG + std::cout << "Div: " << fabs (rts[k] - r) << " " + << fabs (rts[k + 1] - i) << "\n"; +#endif + + if ((fabs (rts[k] - r) > ROOT_TOL) || (fabs (rts[k + 1] - i) > ROOT_TOL)) { + rtsp[j] = rts[k]; + rtsp[j + 1] = rts[k + 1]; + j += 2; + } + + else { + if (i != 0) + // If complex root, eliminates also next root (conjugate) + k += 2; + + found = true; + } + } + + if (!found) { + delete[] rtsp; + std::cout << "Div () : factor not found! \n"; + return; + } + + delete[] rts; + rts = rtsp; + + if (i == 0) + d--; + else + d -= 2; + + rep = ROOTS; +} + +// Simplifies polynoms : eliminates common roots +void smpf (qf_poly & N, qf_poly & D) { + unsigned dN = N.d; + unsigned dD = D.d; + unsigned i, j; + + std::cout << "dN: " << dN << " dD : " << dD << '\n'; + + bool * Ln = new bool[dN]; + bool * Ld = new bool[dD]; + + // Init + for (i = 0; i < dN; i++) + Ln[i] = true; + + for (i = 0; i < dD; i++) + Ld[i] = true; + + if (N.rep == COEFF) + N.to_roots (); + + if (D.rep == COEFF) + D.to_roots (); + + // Seek for common roots + + unsigned ndN = dN; + unsigned ndD = dD; + + for (i = 0; i < 2 * dN; i += 2) { + for (j = 0; j < 2 * dD; j += 2) { + std::cout << "N.rts[" << i << "] = " << N.rts[i] << ", "; + std::cout << "D.rts[" << j << "] = " << D.rts[j] << "\n"; + std::cout << "N.rts[" << i + 1 << "] = " << N.rts[i + 1] << ", "; + std::cout << "D.rts[" << j + 1 << "] = " << D.rts[j + 1] << "\n"; + if ((Ld[j / 2]) && + (fabs (N.rts[i] - D.rts[j]) < ROOT_TOL) && + (fabs (N.rts[i + 1] - D.rts[j + 1]) < ROOT_TOL)) { + Ln[i / 2] = false; // Eliminates both roots + Ld[j / 2] = false; + ndN--; + ndD--; + std::cout << "Common root: (" << D.rts[j] + << ", " << D.rts[j + 1] << "i)\n"; + break; // Direct to next root + } + } + } + + if (ndN != dN) { // We have simplified sth + qf_double_t * nrN = new qf_double_t[2 * ndN]; + qf_double_t * nrD = new qf_double_t[2 * ndD]; + + for (i = 0, j = 0; i < 2 * dN; i += 2) { + if (Ln[i / 2]) { // Non common root + nrN[j] = N.rts[i]; + nrN[j + 1] = N.rts[i + 1]; + j += 2; + } + } + + delete[] N.rts; + N.rts = nrN; + N.d = ndN; + N.rep = ROOTS; + + for (i = 0, j = 0; i < 2 * D.d; i += 2) { + if (Ld[i / 2]) { // Non common root + nrD[j] = D.rts[i]; + nrD[j + 1] = D.rts[i + 1]; + j += 2; + } + } + + delete[] D.rts; + D.rts = nrD; + D.d = ndD; + D.rep = ROOTS; + + N.to_coeff (); + D.to_coeff (); + std::cout << "ndN: " << ndN << " ndD : " << ndD << '\n'; + } + delete[] Ln; + delete[] Ld; +} + +// Hurwitzes a polynom. That is to say, eliminate its roots whose real part +// is positive +void qf_poly::hurw () { + if (rep == NONE) { + std::cout << "qf_poly::hurw () used on a NONE polynom.\n"; + return; + } + + if (rep == COEFF) + to_roots (); + + qf_double_t * rtsp = new qf_double_t[2 * d]; + unsigned j = 0; + + for (unsigned i = 0; i < 2 * d; i += 2) { + if (rts[i] > 0) + if (rts[i + 1] == 0) // Real positive root + continue; + + else { + i += 2; // Skips conjugate + continue; + } + + else { + rtsp[j] = rts[i]; + rtsp[j + 1] = rts[i + 1]; + j += 2; + } + } + + delete[] rts; + rts = rtsp; + d = j / 2; + + if (krts < 0) + krts = -krts; + + rep = ROOTS; +} + +// Evaluates a polynom. Computes P(a) for real a +qf_double_t qf_poly::eval (qf_double_t a) { + if (rep == NONE) { + std::cout << "qf_poly::eval () used on a NONE polynom.\n"; + return 0; + } + + if ((rep == COEFF) || (rep == BOTH)) { + + if (d == 0) + return p[0]; // Constant + + qf_double_t r = p[d]; + + for (int i = d - 1; i >= 0; i--) + r = r * a + p[i]; + + return r; + } + // ROOTS form : P (a) = k prod (a - r[i]) + if (d == 0) + return krts; + + qf_double_t r = krts; + + for (unsigned i = 0; i < 2 * d; i += 2) { + if (rts[i + 1] == 0) // Real root + r *= (a - rts[i]); + + else { + qf_double_t m = rts[i] * rts[i] + rts[i + 1] * rts[i + 1]; + qf_double_t n = -2 * rts[i]; + + r *= (a * a + n * a + m); + i += 2; // Skips conjugate (following root) + } + } + + return r; +} + +// Evaluates a polynom P(X^2) for X^2 = c (c can be negative) +qf_double_t qf_poly::evalX2 (qf_double_t c) { + return (sqr ()).eval (c); +} + +#ifdef _QF_POLY_DEBUG +// Pretty prints a polynom +void qf_poly::disp (const char *name) { + + if (rep == NONE) { + std::cout << name << "(x) is not initalized.\n"; + return; + } + + if ((rep == COEFF) || (rep == BOTH)) { + std::cout << name << "(x) = "; + disp_c (); + } + + if ((rep == ROOTS) || (rep == BOTH)) { + std::cout << name << "(x) = "; + disp_r (); + } +} +#else +void qf_poly::disp (const char *) { } +#endif // _QF_POLY_DEBUG + +void qf_poly::disp_c (void) { + if (d == 0) { + std::cout << p[0] << '\n'; + return; + } + + if (p[d] < 0) + std::cout << "-"; + + if (fabs (p[d]) != 1) + std::cout << fabs (p[d]); + + if (d == 1) { + std::cout << " x "; + } + + else { + std::cout << " x^" << d << ' '; + + for (unsigned i = d - 1; i > 1; i--) { + if (p[i] == 0) // Null monome + continue; + + if (p[i] > 0) + std::cout << "+ "; + else + std::cout << "- "; + + if (fabs (p[i]) != 1) + std::cout << fabs (p[i]); + + std::cout << " x^" << i << ' '; + } + + if (p[1] != 0) { + if (p[1] > 0) + std::cout << "+ "; + else + std::cout << "- "; + + if (fabs (p[1]) != 1) + std::cout << fabs (p[1]); + + std::cout << " x "; + } + } + + if (p[0] != 0) { + if (p[0] > 0) + std::cout << "+ "; + else + std::cout << "- "; + + std::cout << fabs (p[0]); + + } + std::cout << '\n'; +} + +void qf_poly::disp_r (void) { + if (krts == -1) + std::cout << "- "; + + else if (krts != 1) + std::cout << krts << ' '; + + for (unsigned i = 0; i < 2 * d; i += 2) { + if (rts[i + 1] == 0) { // Real root + std::cout << "(X"; + + if (rts[i] == 0) + std::cout << ") "; + + else if (rts[i] < 0) + std::cout << " + " << fabs (rts[i]) << ") "; + + else + std::cout << " - " << rts[i] << ") "; + } + else { // Complex conjugate root + std::cout << "(X^2 "; + + qf_double_t m = rts[i] * rts[i] + rts[i + 1] * rts[i + 1]; + qf_double_t n = 2 * rts[i]; + + if (n > 0) + std::cout << "- " << n << "X "; + + if (n < 0) + std::cout << "+ " << fabs (n) << "X "; + + std::cout << "+ " << m << ") "; + + i += 2; // Skips next root (conjugate of present one) + } + } + std::cout << '\n'; +} + +/* This function calculates P(X) = sum (a[i] * X^i) (sum form) out of + the roots (product form) P(X) = k * prod (X - r[i]) */ +void qf_poly::to_coeff (void) { + if (rep == NONE) { + std::cout << "qf_poly::to_coeff () used on a NONE polynom.\n"; + exit (-1); + } + + if ((rep == COEFF) || (rep == BOTH)) + return; + + if (p != NULL) + delete[] p; + + rep = BOTH; + + p = new qf_double_t[1]; + p[0] = krts; + + if ((rts == NULL) || (d == 0)) + return; + + if (d == 1) { + p = new qf_double_t[2]; + p[0] = -krts * rts[0]; + p[1] = krts; + return; + } + + unsigned r = 0; + + do { + if (rts[2 * r + 1] == 0) { // Real root + qf_double_t *q = new qf_double_t[r + 2]; + + q[0] = 0; + memcpy (&(q[1]), p, sizeof (qf_double_t) * (r + 1)); // Q(X) = XP(X) + + for (unsigned j = 0; j < r + 1; j++) + q[j] -= rts[2 * r] * p[j]; // Q(X) -= r[i]P(X) + + delete[] p; + p = q; + r++; + } + + else { // Complex conjugate root + qf_double_t m, n; + qf_double_t *q = new qf_double_t[r + 3]; + qf_double_t *s = new qf_double_t[r + 2]; + + m = rts[2 * r] * rts[2 * r] + rts[2 * r + 1] * rts[2 * r + 1]; + n = -2 * rts[2 * r]; + + q[0] = q[1] = s[0] = 0; + + memcpy (&(q[2]), p, sizeof (qf_double_t) * (r + 1)); // Q(X) = X^2P(X) + memcpy (&(s[1]), p, sizeof (qf_double_t) * (r + 1)); // S(X) = XP(X) + + for (unsigned j = 0; j < r + 1; j++) // Q(X) = (X^2 + nX + m) P(X) + q[j] += n * s[j] + m * p[j]; + + q[r + 1] += n * s[r + 1]; + + delete[] p; + delete[] s; + p = q; + r += 2; + } + } + while (r < d); + + (*this).disp ("qf_poly::to_coeff: "); +} + +/* The function finds the complex roots of the polynom given by: + p(x) = a_{n-1} * x^{n-1} + ... a_{2} * x^{2} + a_{1} * x + a_{0} + The results are stored in the vector rst, real part followed by + imaginary part for each complex root. It return zero on success + and non-zero otherwise. */ +void qf_poly::to_roots (void) { + if (rep == NONE) { + std::cout << "qf_poly::to_roots () used on a NONE polynom.\n"; + exit (-1); + } + + int status; + + if ((rep == ROOTS) || (rep == BOTH)) + return; // Nothing to do + + if (d == 0) + // cannot solve for only one term + return; + + qf_matrix m (d); + + if (rts != NULL) + delete[] rts; + + rts = new qf_double_t[2 * d]; + + krts = p[d]; + + qf_scm (m); + qf_bcm (m); + status = qf_qrc (m, rts); + + // root solving qr method failed to converge + for (unsigned i = 0; i < 2 * d; i++) { + if (fabs (rts[i]) <= ROOT_PREC) + rts[i] = 0; + else + rts[i] = ROUND_ROOT (rts[i]); +// std::cout << "root(" << i/2 << ") = " << rts [i] << +// " + " << rts [i+1] << " i\n" ; + } + + rep = BOTH; +} + +// Private functions used by qf_poly::solve + +// Set companion matrix. +void qf_poly::qf_scm (qf_matrix & m) { + unsigned int i, j; + for (i = 0; i < m.n; i++) + for (j = 0; j < m.n; j++) + m (i, j) = 0; + + for (i = 1; i < m.n; i++) + m (i, i - 1) = 1; + + for (i = 0; i < m.n; i++) + m (i, m.n - 1) = -p[i] / p[m.n]; +} + +// Balance companion matrix +void qf_poly::qf_bcm (qf_matrix & m) { + int not_converged = 1; + qf_double_t row_norm = 0; + qf_double_t col_norm = 0; + + while (not_converged) { + unsigned int i, j; + qf_double_t g, f, s; + + not_converged = 0; + + for (i = 0; i < m.n; i++) { + /* column norm, excluding the diagonal */ + if (i != m.n - 1) { + col_norm = fabs (m (i + 1, i)); + } + + else { + col_norm = 0; + + for (j = 0; j < m.n - 1; j++) { + col_norm += fabs (m (j, m.n - 1)); + } + } + + /* row norm, excluding the diagonal */ + if (i == 0) { + row_norm = fabs (m (0, m.n - 1)); + } + + else if (i == m.n - 1) { + row_norm = fabs (m (i, i - 1)); + } + + else { + row_norm = fabs (m (i, i - 1)) + fabs (m (i, m.n - 1)); + } + + if ((col_norm == 0) || (row_norm == 0)) { + continue; + } + + g = row_norm / RADIX; + f = 1; + s = col_norm + row_norm; + + while (col_norm < g) { + f *= RADIX; + col_norm *= RADIX2; + } + + g = row_norm * RADIX; + + while (col_norm > g) { + f /= RADIX; + col_norm /= RADIX2; + } + + if ((row_norm + col_norm) < 0.95 * s * f) { + not_converged = 1; + g = 1 / f; + if (i == 0) { + m (0, m.n - 1) *= g; + } + + else { + m (i, i - 1) *= g; + m (i, m.n - 1) *= g; + } + + if (i == m.n - 1) { + for (j = 0; j < m.n; j++) { + m (j, i) *= f; + } + } + else { + m (i + 1, i) *= f; + } + } + } + } +} + +// Root solver using QR method. +int qf_poly::qf_qrc (qf_matrix & h, qf_double_t * zroot) { + qf_double_t t = 0; + unsigned int iterations, e, i, j, k, m; + qf_double_t w, x, y, s, z; + qf_double_t p = 0, q = 0, r = 0; + int notlast; + unsigned int n = d; + +next_root: + if (n == 0) + return 0; + iterations = 0; + +next_iteration: + for (e = n; e >= 2; e--) { + qf_double_t a1 = fabs (h (e - 1, e - 2)); + qf_double_t a2 = fabs (h (e - 2, e - 2)); + qf_double_t a3 = fabs (h (e - 1, e - 1)); + + if (a1 <= EPSILON * (a2 + a3)) + break; + } + + x = h (n - 1, n - 1); + + if (e == n) { + SET_COMPLEX_PACKED (zroot, n - 1, x + t, 0); /* one real root */ + n--; + goto next_root; + } + + y = h (n - 2, n - 2); + w = h (n - 2, n - 1) * h (n - 1, n - 2); + + if (e == n - 1) { + p = (y - x) / 2; + q = p * p + w; + y = sqrt (fabs (q)); + x += t; + + if (q > 0) { /* two real roots */ + if (p < 0) + y = -y; + + y += p; + SET_COMPLEX_PACKED (zroot, n - 1, x - w / y, 0); + SET_COMPLEX_PACKED (zroot, n - 2, x + y, 0); + } + + else { + SET_COMPLEX_PACKED (zroot, n - 1, x + p, -y); + SET_COMPLEX_PACKED (zroot, n - 2, x + p, y); + } + + n -= 2; + goto next_root; + } + + /* No more roots found yet, do another iteration */ + if (iterations == MAX_ITERATIONS) { /* increased from 30 to 60 */ + /* too many iterations - give up! */ + return -1; + } + + if (iterations % 10 == 0 && iterations > 0) { + /* use an exceptional shift */ + t += x; + + for (i = 0; i < n; i++) { + h (i, i) -= x; + } + + s = fabs (h (n - 1, n - 2)) + fabs (h (n - 2, n - 3)); + y = 0.75 * s; + x = y; + w = -0.4375 * s * s; + } + + iterations++; + + for (m = n - 2; m >= e; m--) { + qf_double_t a1, a2, a3; + + z = h (m - 1, m - 1); + r = x - z; + s = y - z; + p = h (m - 1, m) + (r * s - w) / h (m, m - 1); + q = h (m, m) - z - r - s; + r = h (m + 1, m); + s = fabs (p) + fabs (q) + fabs (r); + p /= s; + q /= s; + r /= s; + + if (m == e) + break; + + a1 = fabs (h (m - 1, m - 2)); + a2 = fabs (h (m - 2, m - 2)); + a3 = fabs (h (m, m)); + + if (a1 * (fabs (q) + fabs (r)) <= EPSILON * fabs (p) * (a2 + a3)) + break; + } + + for (i = m + 2; i <= n; i++) { + h (i - 1, i - 3) = 0; + } + for (i = m + 3; i <= n; i++) { + h (i - 1, i - 4) = 0; + } + + /* double QR step */ + for (k = m; k <= n - 1; k++) { + notlast = (k != n - 1); + + if (k != m) { + p = h (k - 1, k - 2); + q = h (k, k - 2); + r = notlast ? h (k + 1, k - 2) : 0; + x = fabs (p) + fabs (q) + fabs (r); + + if (x == 0) + continue; /* FIXME????? */ + + p /= x; + q /= x; + r /= x; + } + + s = sqrt (p * p + q * q + r * r); + + if (p < 0) + s = -s; + + if (k != m) { + h (k - 1, k - 2) = -s * x; + } else if (e != m) { + h (k - 1, k - 2) *= -1; + } + + p += s; + x = p / s; + y = q / s; + z = r / s; + q /= p; + r /= p; + + /* do row modifications */ + for (j = k; j <= n; j++) { + p = h (k - 1, j - 1) + q * h (k, j - 1); + + if (notlast) { + p += r * h (k + 1, j - 1); + h (k + 1, j - 1) -= p * z; + } + + h (k, j - 1) -= p * y; + h (k - 1, j - 1) -= p * x; + } + j = (k + 3 < n) ? (k + 3) : n; + + /* do column modifications */ + for (i = e; i <= j; i++) { + p = x * h (i - 1, k - 1) + y * h (i - 1, k); + + if (notlast) { + p += z * h (i - 1, k + 1); + h (i - 1, k + 1) -= p * r; + } + + h (i - 1, k) -= p * q; + h (i - 1, k - 1) -= p; + } + } + + goto next_iteration; +} + + +void qf_poly::roots_to_complex(QVector< std::complex > &roots) +{ + roots.clear(); + for (unsigned int i=0;i(rts[2*i],rts[2*i+1])); + } +} diff --git a/qf_poly.h b/qf_poly.h new file mode 100644 index 0000000000..06e61146dd --- /dev/null +++ b/qf_poly.h @@ -0,0 +1,142 @@ +/*************************************************************************** + qf_poly.h + ---------------- + begin : Mon Jan 02 2006 + copyright : (C) 2006 by Vincent Habchi, F5RCS + email : 10.50@free.fr + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include +#include + +#ifndef _QF_POLY_H +#define _QF_POLY_H + +/* Headers for R[X] arithmetic */ + +#define qf_double_t long double + +#include "qf_matrix.h" + +// A polynom can be described either by a product of monoms equal to +// (x - r[i]) where r[i] is the ith root and a constant factor, or by +// the classical series of coefficient a[0]...a[n], or both. + +enum qf_poly_rep +{ + NONE = 0, // Not initialized + ROOTS = 1, // P(X) = k * prod (x - r[i]) + COEFF = 2, // P(X) = sum (a[i] * x^i) + BOTH = 3 // Both have been computed +}; + +typedef enum qf_poly_rep qpr; + +class qf_poly +{ + private: + qpr rep; // Type of representation + unsigned d; // Current degree + qf_double_t krts; // Constant k + qf_double_t * p; // Table of coefficients + qf_double_t * rts; // Table of complex roots + + // Functions used by solve + void qf_bcm (qf_matrix &); + int qf_qrc (qf_matrix &, qf_double_t *); + void qf_scm (qf_matrix &); + + public: + qf_poly (); + qf_poly (unsigned); // id with d + qf_poly (qf_double_t, qf_double_t, qf_double_t, unsigned); // Up to d=2 + qf_poly (int, const qf_double_t[]); // Id, with inst. + qf_poly (int, qf_double_t, const qf_double_t[]); + qf_poly (const qf_poly &); // Copy + ~qf_poly (); + + // access operators + qf_poly & operator = (const qf_poly &); // P = Q + qf_double_t & operator [] (int i); // Access to element + + // arithmetic operators + qf_poly operator - (void); // Unary - + + friend qf_poly operator + (qf_poly, qf_poly); + friend qf_poly operator - (qf_poly, qf_poly); + friend qf_poly operator * (qf_poly, qf_poly); + friend qf_poly operator * (qf_poly, const qf_double_t); + + qf_poly operator += (qf_poly); + qf_poly operator -= (qf_poly); + qf_poly operator *= (qf_poly); // P(X) = P(X)*Q(X) + qf_poly operator *= (const qf_double_t); + + qf_poly operator << (unsigned); // Basic div by X^n + qf_poly operator >> (unsigned); // Multiply by X^n + + bool operator == (qf_poly); // Test + bool operator != (qf_poly); // Test + bool is_null (void); + + unsigned deg (void); // Degree of poly + void spl (void); // Simplify + qf_poly odd (void); // Odd part + qf_poly even (void); // Even part + qf_poly mnx (void); // P(X) -> P(-X) + qf_poly hsq (void); // P(X)*P(-X) + qf_poly sqr (void); // Q(X) = P(X^2) + qf_double_t eval (qf_double_t); // P(X = a) + qf_double_t evalX2 (qf_double_t); // P(X^2 = a) + + void to_roots (void); // Solves + qf_double_t k (void); // Return krts factor + void to_coeff (void); // Calculate normal form + void div (qf_double_t, qf_double_t); // Simple division + void hurw (void); // "Hurwitzes" polynom + + void disp (const char *); // Prints P(X) + void disp_c (void); + void disp_r (void); + + void roots_to_complex(QVector< std::complex > &roots); + + friend void smpf (qf_poly &, qf_poly &); // Simplify +}; + +// For solve, we need some gibber + +// Save complex value elements +#define SET_COMPLEX_PACKED(zp,n,r,i) \ + *((zp)+2*(n)+0)=(r); *((zp)+2*(n)+1)=(i); + +// Some constants + +// IEEE long precision 2^{-52} +// # define EPSILON 2.2204460492503131e-16 +// IEEE double long precision 2^{-63} +#define EPSILON 1.0842021724855044e-19 +#define ROOT_PREC 1e-9 +#define ROOT_TOL 1e-7 + +inline qf_double_t ROUND_ROOT (qf_double_t k) { + if (k > 0) + return floor (k / ROOT_PREC) * ROOT_PREC; + else + return ceil (k / ROOT_PREC) * ROOT_PREC; +} + +#define RADIX 2 +#define RADIX2 (RADIX*RADIX) +#define MAX_ITERATIONS 60 + +#endif // _QF_POLY_H + diff --git a/sallenkey.cpp b/sallenkey.cpp index 734401098e..5d50eb062f 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -14,11 +14,11 @@ void SallenKey::calcLowPass() { float R1,R2,R3,R4,C1,C2; float Wc = 2*M_PI*Fc; - float Nst = Nfil/2 + Nfil%2; + float Nst = order/2 + order%2; float Kv1 = pow(Kv,1.0/Nst); qDebug()<\n").arg(dx-20).arg(dx-50); } s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); - if ((2*i)==Nfil) { + if ((2*i)==order) { s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); } else { s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); @@ -188,8 +188,8 @@ void SallenKey::createLowPassSchematic(QString &s) int const N_C=2; // number of capacitors in 2-order Sallen-Key stage RC_elements stage; int dx = 0; - int N2ord = Nfil/2; // number of 2-nd order stages - int N1stOrd = Nfil%2; // number of 1-st order stages + int N2ord = order/2; // number of 2-nd order stages + int N1stOrd = order%2; // number of 1-st order stages s += "\n"; s += "\n"; @@ -232,7 +232,7 @@ void SallenKey::createLowPassSchematic(QString &s) s += QString("<%1 160 %2 160 \"\" 0 0 0 \"\">\n").arg(dx-20).arg(dx-50); } s += QString("<%1 70 %2 70 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(460+dx); - if ((2*i)==Nfil) { + if ((2*i)==order) { s += QString("<%1 70 %2 160 \"out\" %3 90 51 \"\">\n").arg(460+dx).arg(460+dx).arg(490+dx); } else { s += QString("<%1 70 %2 160 \"\" 0 0 0 \"\">\n").arg(460+dx).arg(460+dx); From e7a5ec809f3fdfb32d602bf25923c0cadf505f35 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 1 May 2014 15:21:10 +0400 Subject: [PATCH 31/90] Added checking for proper filter type in calcFilter() --- filter.cpp | 10 ++++++---- filter.h | 6 +++--- filtersintez.cpp | 26 ++++++++++++++------------ 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/filter.cpp b/filter.cpp index 5e2990e35a..c1c9acaa1e 100644 --- a/filter.cpp +++ b/filter.cpp @@ -9,7 +9,7 @@ Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) Rp = par.Rp; As = par.As; Ap = par.Ap; - Kv = par.Kv; // gain of 1 stage + Kv = par.Kv; } Filter::~Filter() @@ -44,7 +44,7 @@ void Filter::createLowPassSchematic(QString &s) } -void Filter::calcFilter() +bool Filter::calcFilter() { Stages.clear(); Poles.clear(); @@ -55,7 +55,8 @@ void Filter::calcFilter() break; case Filter::Butterworth : calcButterworth(); break; - default : break; + default : return false; + break; } switch (ftype) { @@ -63,13 +64,14 @@ void Filter::calcFilter() break; case Filter::HighPass : calcHighPass(); break; - default: + default: return false; break; } Nr = Nr1*(order/2); Nc = Nc1*(order/2); Nopamp = Nop1*order/2; + return true; } diff --git a/filter.h b/filter.h index ebdb49fe06..d7e346e83d 100644 --- a/filter.h +++ b/filter.h @@ -28,8 +28,8 @@ class Filter { public: - enum FType {HighPass, LowPass, BandPass}; - enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev}; + enum FType {HighPass, LowPass, BandPass, NoFilter}; + enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc}; protected: QVector< std::complex > Poles; @@ -71,7 +71,7 @@ class Filter virtual void createSchematic(QString &s); - virtual void calcFilter(); + virtual bool calcFilter(); }; diff --git a/filtersintez.cpp b/filtersintez.cpp index b7cb2bcf66..64ec9a9931 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -141,7 +141,7 @@ void FilterSintez::slotCalcSchematic() par.Kv = pow(10,G/20.0); QStringList lst; - Filter::FilterFunc ffunc; + Filter::FilterFunc ffunc = Filter::NoFunc; switch (cbxFilterFunc->currentIndex()) { case 0 : ffunc = Filter::Butterworth; @@ -155,7 +155,7 @@ void FilterSintez::slotCalcSchematic() default: break; } - Filter::FType ftyp; + Filter::FType ftyp = Filter::NoFilter; if (btnHighPass->isChecked()) { ftyp = Filter::HighPass; } else { @@ -171,21 +171,23 @@ void FilterSintez::slotCalcSchematic() case 1 : { QString s; MFBfilter mfb(ffunc,ftyp,par); - mfb.calcFilter(); - mfb.createPolesZerosList(lst); - mfb.createPartList(lst); - mfb.createSchematic(s); - txtResult->setText(lst.join("\n")); + if (mfb.calcFilter()) { + mfb.createPolesZerosList(lst); + mfb.createPartList(lst); + mfb.createSchematic(s); + txtResult->setText(lst.join("\n")); + } } break; case 2 : { QString s; SallenKey sk(ffunc,ftyp,par); - sk.calcFilter(); - sk.createPolesZerosList(lst); - sk.createPartList(lst); - sk.createSchematic(s); - txtResult->setText(lst.join("\n")); + if (sk.calcFilter()) { + sk.createPolesZerosList(lst); + sk.createPartList(lst); + sk.createSchematic(s); + txtResult->setText(lst.join("\n")); + } } break; case 3 : calcPassive(); From 793b4caec8dbf35d39742b3d49e13167907f3b88 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 1 May 2014 17:29:20 +0400 Subject: [PATCH 32/90] Added Cauer poles and zeros calculation routines --- filter.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- filter.h | 5 +++ 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/filter.cpp b/filter.cpp index c1c9acaa1e..5190366eaf 100644 --- a/filter.cpp +++ b/filter.cpp @@ -36,12 +36,12 @@ void Filter::createSchematic(QString &s) void Filter::createHighPassSchematic(QString &s) { - + s = "\n"; } void Filter::createLowPassSchematic(QString &s) { - + s = "\n"; } bool Filter::calcFilter() @@ -55,6 +55,8 @@ bool Filter::calcFilter() break; case Filter::Butterworth : calcButterworth(); break; + case Filter::Cauer : calcCauer(); + break; default : return false; break; } @@ -259,3 +261,95 @@ void Filter::calcButterworth() order = Poles.count(); } + +void Filter::cauerOrderEstim() // from Digital Filter Design Handbook page 102 +{ + float k = Fc/Fs; + float kk = sqrt(sqrt(1.0-k*k)); + float u = 0.5*(1.0-kk)/(1.0+kk); + float q = 150.0*pow(u,13) + 2.0*pow(u,9) + 2.0*pow(u,5) + u; + float dd = (pow(10.0,As/10.0)-1.0)/(pow(10.0,Rp/10.0)-1.0); + order = ceil(log10(16.0*dd)/log10(1.0/q)); +} + +void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 +{ + float P0; + //float H0; + float mu; + float aa[50],bb[50],cc[50]; + + cauerOrderEstim(); + float k = Fc/Fs; + float kk = sqrt(sqrt(1.0-k*k)); + float u = 0.5*(1.0-kk)/(1.0+kk); + float q = 150.0*pow(u,13) + 2.0*pow(u,9) + 2.0*pow(u,5) + u; + float numer = pow(10.0,Rp/20.0)+1.0; + float vv = log(numer/(pow(10.0,Rp/20.0)-1.0))/(2.0*order); + float sum = 0.0; + for (int m=0;m<5;m++) { + float term = pow(-1.0,m); + term = term*pow(q,m*(m+1)); + term = term*sinh((2*m+1)*vv); + sum = sum +term; + } + numer = 2.0*sum*sqrt(sqrt(q)); + + sum=0.0; + for (int m=1;m<5;m++) { + float term = pow(-1.0,m); + term = term*pow(q,m*m); + term = term*cosh(2.0*m*vv); + sum += term; + } + float denom = 1.0+2.0*sum; + P0 = fabs(numer/denom); + float ww = 1.0+k*P0*P0; + ww = sqrt(ww*(1.0+P0*P0/k)); + int r = (order-(order%2))/2; + //float numSecs = r; + + for (int i=1;i<=r;i++) { + if ((order%2)!=0) { + mu = i; + } else { + mu = i-0.5; + } + sum = 0.0; + for(int m=0;m<5;m++) { + float term = pow(-1.0,m)*pow(q,m*(m+1)); + term = term*sin((2*m+1)*M_PI*mu/order); + sum += term; + } + numer = 2.0*sum*sqrt(sqrt(q)); + + sum = 0.0; + for(int m=1;m<5;m++) { + float term = pow(-1.0,m)*pow(q,m*m); + term = term*cos(2.0*m*M_PI*mu/order); + sum += term; + } + denom = 1.0+2.0*sum; + float xx = numer/denom; + float yy = 1.0 - k*xx*xx; + yy = sqrt(yy*(1.0-(xx*xx/k))); + aa[i-1] = 1.0/(xx*xx); + denom = 1.0 + pow(P0*xx,2); + bb[i-1] = 2.0*P0*yy/denom; + denom = pow(denom,2); + numer = pow(P0*yy,2)+pow(xx*ww,2); + cc[i-1] = numer/denom; + } + + Zeros.clear(); + Poles.clear(); + for (int i=0;i(0,im)); + Zeros.append(std::complex(0,-im)); + float re = -0.5*bb[i]; + im = 0.5*sqrt(-1.0*bb[i]*bb[i]+4*cc[i]); + Poles.append(std::complex(re,im)); + Poles.append(std::complex(re,-im)); + } +} diff --git a/filter.h b/filter.h index d7e346e83d..bb8dd9015e 100644 --- a/filter.h +++ b/filter.h @@ -31,6 +31,10 @@ class Filter enum FType {HighPass, LowPass, BandPass, NoFilter}; enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc}; +private: + void besselCoefficients(); + void cauerOrderEstim(); + protected: QVector< std::complex > Poles; QVector< std::complex > Zeros; @@ -47,6 +51,7 @@ class Filter void calcButterworth(); void calcChebyshev(); void calcCauer(); + void calcBessel(); void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx); From fed3292250f91bcaca90f4a9f58964c4fe8f6769 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 2 May 2014 12:48:34 +0400 Subject: [PATCH 33/90] Fixed poles calculation for odd order Cauer filter --- filter.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/filter.cpp b/filter.cpp index 5190366eaf..ee88600069 100644 --- a/filter.cpp +++ b/filter.cpp @@ -141,7 +141,7 @@ void Filter::createPartList(QStringList &lst) void Filter::createPolesZerosList(QStringList &lst) { - lst< pole; foreach(pole,Poles) { @@ -341,6 +341,11 @@ void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 cc[i-1] = numer/denom; } + if (order%2!=0) { + cc[order-1] = P0; // first order section + bb[order-1] = 0; + } + Zeros.clear(); Poles.clear(); for (int i=0;i(re,im)); Poles.append(std::complex(re,-im)); } + if (order%2!=0) { + Poles.append(std::complex(-cc[order-1],0.0)); + } } From dc9182eab40cd251096a2b867c177ffcc20c3fb8 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 2 May 2014 15:53:24 +0400 Subject: [PATCH 34/90] Implemented poles and zeros table proper formatting --- filter.cpp | 11 +++++++++-- sallenkey.cpp | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/filter.cpp b/filter.cpp index ee88600069..7c06993c11 100644 --- a/filter.cpp +++ b/filter.cpp @@ -351,13 +351,20 @@ void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 for (int i=0;i(0,im)); - Zeros.append(std::complex(0,-im)); float re = -0.5*bb[i]; im = 0.5*sqrt(-1.0*bb[i]*bb[i]+4*cc[i]); Poles.append(std::complex(re,im)); - Poles.append(std::complex(re,-im)); } + if (order%2!=0) { Poles.append(std::complex(-cc[order-1],0.0)); } + + for (int i=r-1;i>=0;i--) { + float im = sqrt(aa[i]); + Zeros.append(std::complex(0,-im)); + float re = -0.5*bb[i]; + im = 0.5*sqrt(-1.0*bb[i]*bb[i]+4*cc[i]); + Poles.append(std::complex(re,-im)); + } } diff --git a/sallenkey.cpp b/sallenkey.cpp index 5d50eb062f..0809dc0d06 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -14,7 +14,7 @@ void SallenKey::calcLowPass() { float R1,R2,R3,R4,C1,C2; float Wc = 2*M_PI*Fc; - float Nst = order/2 + order%2; + int Nst = order/2 + order%2; float Kv1 = pow(Kv,1.0/Nst); qDebug()< Date: Fri, 2 May 2014 16:10:46 +0400 Subject: [PATCH 35/90] Implemented zeros list printing --- filter.cpp | 13 ++++++++++--- filter.h | 2 +- mfbfilter.cpp | 12 ++++++------ sallenkey.cpp | 16 ++++++++-------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/filter.cpp b/filter.cpp index 7c06993c11..f333f8d242 100644 --- a/filter.cpp +++ b/filter.cpp @@ -46,7 +46,7 @@ void Filter::createLowPassSchematic(QString &s) bool Filter::calcFilter() { - Stages.clear(); + Sections.clear(); Poles.clear(); Zeros.clear(); @@ -118,7 +118,7 @@ void Filter::calcFirstOrder() curr_stage.R4 = 0; curr_stage.C1 = C1; curr_stage.C2 = 0; - Stages.append(curr_stage); + Sections.append(curr_stage); } @@ -130,7 +130,7 @@ void Filter::createPartList(QStringList &lst) lst<<"Stage# C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)"; RC_elements stage; - foreach (stage,Stages) { + foreach (stage,Sections) { QString suff1,suff2; float C1=autoscaleCapacitor(stage.C1,suff1); float C2=autoscaleCapacitor(stage.C2,suff2); @@ -142,6 +142,13 @@ void Filter::createPartList(QStringList &lst) void Filter::createPolesZerosList(QStringList &lst) { lst< zero; + foreach(zero,Zeros) { + lst< pole; foreach(pole,Poles) { diff --git a/filter.h b/filter.h index bb8dd9015e..5c7e39c362 100644 --- a/filter.h +++ b/filter.h @@ -38,7 +38,7 @@ class Filter protected: QVector< std::complex > Poles; QVector< std::complex > Zeros; - QVector Stages; + QVector Sections; Filter::FType ftype; Filter::FilterFunc ffunc; diff --git a/mfbfilter.cpp b/mfbfilter.cpp index 5b6d594e5c..76f9469514 100644 --- a/mfbfilter.cpp +++ b/mfbfilter.cpp @@ -38,7 +38,7 @@ void MFBfilter::createLowPassSchematic(QString &s) s += QString("\n").arg(70+dx); s += QString("\n").arg(70+dx); for (int i=1; i<=N2ord; i++) { - stage = Stages.at(i-1); + stage = Sections.at(i-1); qDebug()<\n").arg(70+dx); s += QString("\n").arg(70+dx); for (int i=1; i<=N2ord; i++) { - stage = Stages.at(i-1); + stage = Sections.at(i-1); qDebug()<calcFirstOrder(); @@ -229,7 +229,7 @@ void MFBfilter::calcLowPass() curr_stage.R4 = 0; curr_stage.C1 = C1; curr_stage.C2 = C2; - Stages.append(curr_stage); + Sections.append(curr_stage); } this->calcFirstOrder(); diff --git a/sallenkey.cpp b/sallenkey.cpp index 0809dc0d06..e28225ec28 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -14,7 +14,7 @@ void SallenKey::calcLowPass() { float R1,R2,R3,R4,C1,C2; float Wc = 2*M_PI*Fc; - int Nst = order/2 + order%2; + float Nst = order/2 + order%2; float Kv1 = pow(Kv,1.0/Nst); qDebug()<calcFirstOrder(); @@ -95,7 +95,7 @@ void SallenKey::calcHighPass() curr_stage.R4 = 1000*R4; curr_stage.C1 = C1; curr_stage.C2 = C1; - Stages.append(curr_stage); + Sections.append(curr_stage); } calcFirstOrder(); } @@ -117,7 +117,7 @@ void SallenKey::createHighPassSchematic(QString &s) s += QString("\n").arg(20+dx); s += QString("\n").arg(20+dx); for (int i=1; i<=N2ord; i++) { - stage = Stages.at(i-1); + stage = Sections.at(i-1); qDebug()<\n").arg(20+dx); s += QString("\n").arg(20+dx); for (int i=1; i<=N2ord; i++) { - stage = Stages.at(i-1); + stage = Sections.at(i-1); qDebug()< Date: Fri, 2 May 2014 16:21:34 +0400 Subject: [PATCH 36/90] Implemented error message for fiter types, which are not yet supported --- filtersintez.cpp | 29 +++++++++++------------------ filtersintez.h | 8 +------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 64ec9a9931..500e2964e6 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -141,7 +141,7 @@ void FilterSintez::slotCalcSchematic() par.Kv = pow(10,G/20.0); QStringList lst; - Filter::FilterFunc ffunc = Filter::NoFunc; + Filter::FilterFunc ffunc; switch (cbxFilterFunc->currentIndex()) { case 0 : ffunc = Filter::Butterworth; @@ -152,7 +152,8 @@ void FilterSintez::slotCalcSchematic() break; case 3 : ffunc = Filter::Cauer; break; - default: break; + default: ffunc = Filter::NoFunc; + break; } Filter::FType ftyp = Filter::NoFilter; @@ -165,8 +166,7 @@ void FilterSintez::slotCalcSchematic() switch (cbxFilterType->currentIndex()) { - case 0 : if (btnHighPass->isChecked()) calcDblQuadHPF(); - else calcDblQuadLPF(); + case 0 : errorMessage(tr("Function unsupported!")); break; case 1 : { QString s; @@ -190,7 +190,7 @@ void FilterSintez::slotCalcSchematic() } } break; - case 3 : calcPassive(); + case 3 : errorMessage(tr("Function unsupported!")); break; default: break; } @@ -217,18 +217,11 @@ void FilterSintez::slotUpdateSchematic() sch_pic->setPixmap(pix); } - -void FilterSintez::calcDblQuadHPF() -{ - -} - -void FilterSintez::calcDblQuadLPF() +void FilterSintez::errorMessage(QString str) { - -} - -void FilterSintez::calcPassive() -{ - + QMessageBox* msg = new QMessageBox(QMessageBox::Critical,tr("Active filter design"), + str, + QMessageBox::Ok); + msg->exec(); + delete msg; } diff --git a/filtersintez.h b/filtersintez.h index f05abdba0c..c616cc3b14 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -55,13 +55,7 @@ class FilterSintez : public QMainWindow QWidget *zenter; - void calcDblQuadLPF(); - void calcDblQuadHPF(); - void calcMultiloopLPF(); - void calcMultiloopHPF(); - void calcSallenKeyLPF(); - void calcSallenKeyHPF(); - void calcPassive(); + void errorMessage(QString s); QVector< std::complex > Poles; From fc2ffcec54a974aa3b6ce4bab9f2421bbfcafcfd Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 3 May 2014 11:07:38 +0400 Subject: [PATCH 37/90] Implemented RC components values checking before writing schematic file --- filter.cpp | 20 ++++++++++++++++++-- filter.h | 1 + filtersintez.cpp | 6 ++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/filter.cpp b/filter.cpp index f333f8d242..3cb3c262a8 100644 --- a/filter.cpp +++ b/filter.cpp @@ -70,10 +70,12 @@ bool Filter::calcFilter() break; } + bool res = checkRCL(); + Nr = Nr1*(order/2); Nc = Nc1*(order/2); Nopamp = Nop1*order/2; - return true; + return res; } @@ -225,7 +227,21 @@ float Filter::autoscaleCapacitor(float C, QString &suffix) return C1; } - +bool Filter::checkRCL() +{ + RC_elements sec; + foreach (sec,Sections) { + if (std::isnan(sec.R1)|| + std::isnan(sec.R2)|| + std::isnan(sec.R3)|| + std::isnan(sec.R4)|| + std::isnan(sec.C1)|| + std::isnan(sec.C2)) { + return false; + } + } + return true; +} void Filter::calcChebyshev() { diff --git a/filter.h b/filter.h index 5c7e39c362..70ac7e1fb8 100644 --- a/filter.h +++ b/filter.h @@ -52,6 +52,7 @@ class Filter void calcChebyshev(); void calcCauer(); void calcBessel(); + bool checkRCL(); // Checks RCL values. Are one of them NaN or not? void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx); diff --git a/filtersintez.cpp b/filtersintez.cpp index 500e2964e6..f1a45feed2 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -176,6 +176,9 @@ void FilterSintez::slotCalcSchematic() mfb.createPartList(lst); mfb.createSchematic(s); txtResult->setText(lst.join("\n")); + } else { + errorMessage(tr("Unable to implement filter with such parameters and topology \n" + "Chnange parapeters and/or topology and try again!")); } } break; @@ -187,6 +190,9 @@ void FilterSintez::slotCalcSchematic() sk.createPartList(lst); sk.createSchematic(s); txtResult->setText(lst.join("\n")); + } else { + errorMessage(tr("Unable to implement filter with such parameters and topology \n" + "Chnange parapeters and/or topology and try again!")); } } break; From 272ae29db0da9854cbbacebd00e4e6ecae4a2190 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 3 May 2014 11:20:18 +0400 Subject: [PATCH 38/90] Added band-pass and band-stop radio buttons for future applications --- filter.h | 2 +- filtersintez.cpp | 20 +++++++++++++++----- filtersintez.h | 2 ++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/filter.h b/filter.h index 70ac7e1fb8..245a22a4fc 100644 --- a/filter.h +++ b/filter.h @@ -28,7 +28,7 @@ class Filter { public: - enum FType {HighPass, LowPass, BandPass, NoFilter}; + enum FType {HighPass, LowPass, BandPass, BandStop, NoFilter}; enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc}; private: diff --git a/filtersintez.cpp b/filtersintez.cpp index f1a45feed2..0006c84844 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -56,9 +56,15 @@ FilterSintez::FilterSintez(QWidget *parent) lblSch = new QLabel(tr("Схемная реализация фильтра")); btnHighPass = new QRadioButton(tr("ФВЧ")); btnLowPass = new QRadioButton(tr("ФНЧ")); + btnBandPass = new QRadioButton(tr("Band-pass")); + btnBandStop = new QRadioButton(tr("Band-stop")); QButtonGroup *grp1 = new QButtonGroup; grp1->addButton(btnHighPass); grp1->addButton(btnLowPass); + grp1->addButton(btnBandPass); + grp1->addButton(btnBandStop); + btnBandPass->setDisabled(true); + btnBandStop->setDisabled(true); btnLowPass->setChecked(true); connect(grp1,SIGNAL(buttonClicked(int)),this,SLOT(slotUpdateSchematic())); @@ -107,6 +113,8 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(lblSch); left->addWidget(btnLowPass); left->addWidget(btnHighPass); + left->addWidget(btnBandPass); + left->addWidget(btnBandStop); left->addWidget(cbxFilterType); left->addWidget(btnCalcSchematic); @@ -159,12 +167,14 @@ void FilterSintez::slotCalcSchematic() Filter::FType ftyp = Filter::NoFilter; if (btnHighPass->isChecked()) { ftyp = Filter::HighPass; - } else { + } else if (btnLowPass->isChecked()) { ftyp = Filter::LowPass; + } else if (btnBandPass->isChecked()) { + ftyp = Filter::BandPass; + } else if (btnBandStop->isChecked()) { + ftyp = Filter::BandStop; } - - switch (cbxFilterType->currentIndex()) { case 0 : errorMessage(tr("Function unsupported!")); break; @@ -178,7 +188,7 @@ void FilterSintez::slotCalcSchematic() txtResult->setText(lst.join("\n")); } else { errorMessage(tr("Unable to implement filter with such parameters and topology \n" - "Chnange parapeters and/or topology and try again!")); + "Change parapeters and/or topology and try again!")); } } break; @@ -192,7 +202,7 @@ void FilterSintez::slotCalcSchematic() txtResult->setText(lst.join("\n")); } else { errorMessage(tr("Unable to implement filter with such parameters and topology \n" - "Chnange parapeters and/or topology and try again!")); + "Change parapeters and/or topology and try again!")); } } break; diff --git a/filtersintez.h b/filtersintez.h index c616cc3b14..b306c28f52 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -40,6 +40,8 @@ class FilterSintez : public QMainWindow QRadioButton *btnLowPass; QRadioButton *btnHighPass; + QRadioButton *btnBandPass; + QRadioButton *btnBandStop; QComboBox *cbxFilterType; From 7db795c4bbd4c5dd17da10f8ebd81a083a5ee62b Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 3 May 2014 16:47:33 +0400 Subject: [PATCH 39/90] Implemented error message for usage MFB filter for Cauer and Inverse Chebyshev transfer functions --- filtersintez.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 0006c84844..a3c61d59e9 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -176,19 +176,24 @@ void FilterSintez::slotCalcSchematic() } switch (cbxFilterType->currentIndex()) { - case 0 : errorMessage(tr("Function unsupported!")); + case 0 : errorMessage(tr("Function will be implemented in future version")); break; case 1 : { QString s; - MFBfilter mfb(ffunc,ftyp,par); - if (mfb.calcFilter()) { - mfb.createPolesZerosList(lst); - mfb.createPartList(lst); - mfb.createSchematic(s); - txtResult->setText(lst.join("\n")); + if (!((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) { + MFBfilter mfb(ffunc,ftyp,par); + if (mfb.calcFilter()) { + mfb.createPolesZerosList(lst); + mfb.createPartList(lst); + mfb.createSchematic(s); + txtResult->setText(lst.join("\n")); + } else { + errorMessage(tr("Unable to implement filter with such parameters and topology \n" + "Change parapeters and/or topology and try again!")); + } } else { - errorMessage(tr("Unable to implement filter with such parameters and topology \n" - "Change parapeters and/or topology and try again!")); + errorMessage(tr("Unable to use MFB filter for Cauer or Inverse Chebyshev \n" + "frequency response. Try to use another topology.")); } } break; @@ -206,7 +211,7 @@ void FilterSintez::slotCalcSchematic() } } break; - case 3 : errorMessage(tr("Function unsupported!")); + case 3 : errorMessage(tr("Function will be implemented in future version")); break; default: break; } From a8a7cb1af6e8a2e2ae23d090fd8e9efbb3538941 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 3 May 2014 17:57:58 +0400 Subject: [PATCH 40/90] Implemented Chebyshev Type-II poles and zeros calculation --- filter.cpp | 31 +++++++++++++++++++++++++++++++ filter.h | 1 + 2 files changed, 32 insertions(+) diff --git a/filter.cpp b/filter.cpp index 3cb3c262a8..8be8e24d6c 100644 --- a/filter.cpp +++ b/filter.cpp @@ -57,6 +57,8 @@ bool Filter::calcFilter() break; case Filter::Cauer : calcCauer(); break; + case Filter::InvChebyshev : calcInvChebyshev(); + break; default : return false; break; } @@ -285,6 +287,35 @@ void Filter::calcButterworth() order = Poles.count(); } +void Filter::calcInvChebyshev() // Chebyshev Type-II filter +{ + Poles.clear(); + Zeros.clear(); + + + + order = ceil(acosh(sqrt(pow(10.0,0.1*As)-1.0))/acosh(Fs/Fc)); + + float eps = 1.0/(sqrt(pow(10.0,0.1*As)-1.0)); + float a = sinh((asinh(1.0/eps))/(order)); + float b = cosh((asinh(1.0/eps))/(order)); + + for (int k=1;k<=order;k++) { + float im = 1.0/(cos(((2*k-1)*M_PI)/(2*order))); + Zeros.append(std::complex(0,im)); + } + + for (int k=1;k<=order;k++) { + float re = -1*a*sin(M_PI*(2*k-1)/(2*order)); + float im = b*cos(M_PI*(2*k-1)/(2*order)); + std::complex invpol(re,im); // inverse pole + std::complex pol; + pol = std::complex(1.0,0) / invpol; // pole + Poles.append(pol); + } + +} + void Filter::cauerOrderEstim() // from Digital Filter Design Handbook page 102 { float k = Fc/Fs; diff --git a/filter.h b/filter.h index 245a22a4fc..055284c63b 100644 --- a/filter.h +++ b/filter.h @@ -50,6 +50,7 @@ class Filter void calcButterworth(); void calcChebyshev(); + void calcInvChebyshev(); void calcCauer(); void calcBessel(); bool checkRCL(); // Checks RCL values. Are one of them NaN or not? From 9655547a7b2347d4c9ea4d35ee231b23684590a9 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 3 May 2014 18:05:58 +0400 Subject: [PATCH 41/90] Implemented input fields enabling depends on filter function type --- filtersintez.cpp | 14 ++++++++++++++ filtersintez.h | 1 + 2 files changed, 15 insertions(+) diff --git a/filtersintez.cpp b/filtersintez.cpp index a3c61d59e9..ace932bcc0 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -46,6 +46,8 @@ FilterSintez::FilterSintez(QWidget *parent) <addItems(lst2); + connect(cbxFilterFunc,SIGNAL(currentIndexChanged(int)),this,SLOT(slotSwitchParameters())); + btnCalcSchematic = new QPushButton(tr("Рассчитать элементы схемы фильтра")); connect(btnCalcSchematic,SIGNAL(clicked()),SLOT(slotCalcSchematic())); @@ -76,6 +78,7 @@ FilterSintez::FilterSintez(QWidget *parent) <addItems(lst); connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); + this->slotSwitchParameters(); imgAFR = new QSvgWidget("AFR.svg"); imgAFR->show(); @@ -238,6 +241,17 @@ void FilterSintez::slotUpdateSchematic() sch_pic->setPixmap(pix); } +void FilterSintez::slotSwitchParameters() +{ + if (cbxFilterFunc->currentIndex()==0) { + edtA1->setEnabled(true); + edtPassbRpl->setEnabled(false); + } else { + edtA1->setEnabled(false); + edtPassbRpl->setEnabled(true); + } +} + void FilterSintez::errorMessage(QString str) { QMessageBox* msg = new QMessageBox(QMessageBox::Critical,tr("Active filter design"), diff --git a/filtersintez.h b/filtersintez.h index b306c28f52..37d7dc029a 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -72,6 +72,7 @@ private slots: void slotUpdateSchematic(); void slotCalcSchematic(); + void slotSwitchParameters(); public: FilterSintez(QWidget *parent = 0); From a9576a3910bd48bdd7ee7303f2b252d76d0733a2 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 4 May 2014 14:25:44 +0400 Subject: [PATCH 42/90] Started implementation of Cauer 2-order filter section topology --- QFilterSintez.pro | 6 ++++-- schcauer.cpp | 31 +++++++++++++++++++++++++++++++ schcauer.h | 23 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 schcauer.cpp create mode 100644 schcauer.h diff --git a/QFilterSintez.pro b/QFilterSintez.pro index 76fb7d68d0..cdcc4a258f 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -17,11 +17,13 @@ SOURCES += main.cpp\ filter.cpp \ sallenkey.cpp \ mfbfilter.cpp \ - qf_poly.cpp + qf_poly.cpp \ + schcauer.cpp HEADERS += filtersintez.h \ filter.h \ sallenkey.h \ mfbfilter.h \ qf_poly.h \ - qf_matrix.h + qf_matrix.h \ + schcauer.h diff --git a/schcauer.cpp b/schcauer.cpp new file mode 100644 index 0000000000..c8451a1e68 --- /dev/null +++ b/schcauer.cpp @@ -0,0 +1,31 @@ +#include "schcauer.h" + +SchCauer::SchCauer(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) : + Filter(ffunc_, type_, par) +{ + Nr = 4; + Nopamp = 3; + Nc = 2; +} + +void SchCauer::calcLowPass() +{ + +} + + +void SchCauer::calcHighPass() +{ + +} + + +void SchCauer::createLowPassSchematic(QString &s) +{ + +} + +void SchCauer::createHighPassSchematic(QString &s) +{ + +} diff --git a/schcauer.h b/schcauer.h new file mode 100644 index 0000000000..20d8b34ae1 --- /dev/null +++ b/schcauer.h @@ -0,0 +1,23 @@ +#ifndef SCHCAUER_H +#define SCHCAUER_H + +#include +#include +#include +#include "filter.h" + +class SchCauer : public Filter // Cauer 2-order section +{ + +protected: + + void calcHighPass(); + void calcLowPass(); + void createHighPassSchematic(QString &s); + void createLowPassSchematic(QString &s); + +public: + SchCauer(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par); +}; + +#endif // SCHCAUER_H From 7284d1ee2e7b34c9cbf3e78cd42e74c1a6f3be62 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 4 May 2014 14:56:08 +0400 Subject: [PATCH 43/90] Implemented calculation of RCL values of Cauer section --- filtersintez.cpp | 13 +++++++++++-- schcauer.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index ace932bcc0..6d61de7399 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -1,6 +1,7 @@ #include "filtersintez.h" #include "sallenkey.h" #include "mfbfilter.h" +#include "schcauer.h" #include @@ -72,7 +73,7 @@ FilterSintez::FilterSintez(QWidget *parent) cbxFilterType = new QComboBox; QStringList lst; - lst<currentIndex()) { - case 0 : errorMessage(tr("Function will be implemented in future version")); + case 0 : { + QString s; + SchCauer cauer(ffunc,ftyp,par); + cauer.calcFilter(); + cauer.createPolesZerosList(lst); + cauer.createPartList(lst); + txtResult->setText(lst.join("\n")); + } + break; case 1 : { QString s; diff --git a/schcauer.cpp b/schcauer.cpp index c8451a1e68..bd5c53942f 100644 --- a/schcauer.cpp +++ b/schcauer.cpp @@ -3,14 +3,51 @@ SchCauer::SchCauer(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) : Filter(ffunc_, type_, par) { - Nr = 4; + Nr = 5; Nopamp = 3; Nc = 2; } void SchCauer::calcLowPass() { + float R1,R2,R3,R4,R5,C1,C2; + float Wc = 2*M_PI*Fc; + float Nst = order/2 + order%2; + float Kv1 = pow(Kv,1.0/Nst); + //qDebug()<calcFirstOrder(); } From 00777e56bdf6473a8af10e708d5639334bc5f3fc Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 4 May 2014 15:17:29 +0400 Subject: [PATCH 44/90] Implemented including of R5 value to part list for Cauer filter --- filter.cpp | 17 ++++++++++++++--- filter.h | 1 + mfbfilter.cpp | 2 ++ sallenkey.cpp | 2 ++ schcauer.cpp | 1 + 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/filter.cpp b/filter.cpp index 8be8e24d6c..6d15b5a545 100644 --- a/filter.cpp +++ b/filter.cpp @@ -131,15 +131,26 @@ void Filter::calcFirstOrder() void Filter::createPartList(QStringList &lst) { lst< Date: Sun, 4 May 2014 15:22:42 +0400 Subject: [PATCH 45/90] Implemented autoselct of cauer topology for Cauer approximation --- filtersintez.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/filtersintez.cpp b/filtersintez.cpp index 6d61de7399..1a01ed09ef 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -259,6 +259,13 @@ void FilterSintez::slotSwitchParameters() edtA1->setEnabled(false); edtPassbRpl->setEnabled(true); } + + if (cbxFilterFunc->currentIndex()==3) { + cbxFilterType->setCurrentIndex(0); + cbxFilterType->setDisabled(true); + } else { + cbxFilterType->setDisabled(false); + } } void FilterSintez::errorMessage(QString str) From 24d8024e25f14c92fb313708470fcea928b7583f Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 4 May 2014 15:50:09 +0400 Subject: [PATCH 46/90] Some correction --- filtersintez.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 1a01ed09ef..7deaf9f00d 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -113,6 +113,7 @@ FilterSintez::FilterSintez(QWidget *parent) center->addWidget(lblResult); center->addWidget(txtResult); txtResult->setMinimumWidth(400); + txtResult->setReadOnly(true); left->addWidget(lblSch); left->addWidget(btnLowPass); @@ -260,7 +261,7 @@ void FilterSintez::slotSwitchParameters() edtPassbRpl->setEnabled(true); } - if (cbxFilterFunc->currentIndex()==3) { + if ((cbxFilterFunc->currentIndex()==3)||(cbxFilterFunc->currentIndex()==2)) { cbxFilterType->setCurrentIndex(0); cbxFilterType->setDisabled(true); } else { From 6c7ecb1e8033f15ab7ace208ecca6841fde91797 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 4 May 2014 16:02:04 +0400 Subject: [PATCH 47/90] Added resource file --- QFilterSintez.pro | 3 +++ filtersintez.cpp | 2 +- qfiltersintez.qrc | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 qfiltersintez.qrc diff --git a/QFilterSintez.pro b/QFilterSintez.pro index cdcc4a258f..188f0912a1 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -27,3 +27,6 @@ HEADERS += filtersintez.h \ qf_poly.h \ qf_matrix.h \ schcauer.h + +RESOURCES += \ + qfiltersintez.qrc diff --git a/filtersintez.cpp b/filtersintez.cpp index 7deaf9f00d..b6297321c3 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -81,7 +81,7 @@ FilterSintez::FilterSintez(QWidget *parent) connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); this->slotSwitchParameters(); - imgAFR = new QSvgWidget("AFR.svg"); + imgAFR = new QSvgWidget(":/images/AFR.svg"); imgAFR->show(); sch_pic = new QLabel; QPixmap pix("Images/dblquad.png"); diff --git a/qfiltersintez.qrc b/qfiltersintez.qrc new file mode 100644 index 0000000000..fcecaf6956 --- /dev/null +++ b/qfiltersintez.qrc @@ -0,0 +1,5 @@ + + + AFR.svg + + From decd314883bbb773a82ee608d9830a186f776662 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 5 May 2014 09:07:02 +0400 Subject: [PATCH 48/90] Raster schematic images replaced by SVG graphics form Qucs --- .gitignore | 2 +- Images/dblquad.png | Bin 3205 -> 0 bytes Images/high-pass1.png | Bin 1497 -> 0 bytes Images/low-pass1.png | Bin 2268 -> 0 bytes Images/multiloop.png | Bin 1674 -> 0 bytes Images/noteven.png | Bin 3026 -> 0 bytes Images/passive.png | Bin 4782 -> 0 bytes filtersintez.cpp | 25 +-- filtersintez.h | 2 +- mfb-highpass.svg | 407 +++++++++++++++++++++++++++++++++++++++ mfb-lowpass.svg | 404 +++++++++++++++++++++++++++++++++++++++ qfiltersintez.qrc | 4 + sk-highpass.svg | 430 ++++++++++++++++++++++++++++++++++++++++++ sk-lowpass.svg | 430 ++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 1690 insertions(+), 14 deletions(-) delete mode 100644 Images/dblquad.png delete mode 100644 Images/high-pass1.png delete mode 100644 Images/low-pass1.png delete mode 100644 Images/multiloop.png delete mode 100644 Images/noteven.png delete mode 100644 Images/passive.png create mode 100644 mfb-highpass.svg create mode 100644 mfb-lowpass.svg create mode 100644 sk-highpass.svg create mode 100644 sk-lowpass.svg diff --git a/.gitignore b/.gitignore index f3d7261b8f..3e017f3124 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ moc_*.cpp *.sch~ *.dat *.dpl - +qrc_*.cpp diff --git a/Images/dblquad.png b/Images/dblquad.png deleted file mode 100644 index 741eefc815d9c5c467cf52788ce6e5f80780703c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3205 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 w|A)cb*V)}Q95f&mC+XN`3qXxk_J4Oe*Ld;kCd diff --git a/Images/high-pass1.png b/Images/high-pass1.png deleted file mode 100644 index 1b45457f7fd1e199d61a8209d10870e7720586c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1497 zcmbtUZ8(z)7=9Uxd5!Y*#vD>4TIU_}HFC@h%SAIEk*RH_OkqB9N}M*?t1>C&93+QM z`jDKYBv&0{K1O0mlw2VaI-wGh)>)@t=lA*XJoj_o_jOlK^l427qZ60FVj+z=&Vc5a^~fR5^Y=UclGvyskzi)8zYxCj$Vs<=dzf*kVnT zRlPJXa`3^ywxXd_-r{Gl9(&;^Ve)j3DjRyV9g7{zgLS#h)m`uGVG z6X|D4U#&PXk6mQNTB7|zbB!{`@f9nHGm$io3d(x7?!*gILj#ueqV}CTVt1O`8AvG9 zm$eBJIH%^zEsMpG!w!*9k+N=(4X&b?+R-pqY*CM&uaUfeY> z4vS^4F-P4oB(njTQ+{A-!c$>yW)S z?_Sj5a)DcNe014Mv6ixEzf!f{v(pq#am(2fCEM@4?|GrP>G}EElkw?3Y!=gEfNApH z75xtKX_3^kCmzq6q=~z^S5@Pi8Fk`|Mc?BSA20bj*>y+Vpuz+bPAMS>$OUpUUz_sk}Jl8==n6$et!I!1DJl?HHu9MRqIk3~ zGkw<(w!pzrxZ*fx1>PFdG1OF#grLgYes?3u18$N%Sn*T@#iMpZD9o&gFl1%d42AO4 z5l+8Eux~;L6)WI<1Z4Zx3{|A<=>dozDT&J&?fv?YVE&2g1ZoPgU`0W;0XW=|QN#D9 zk~lJbW`44{Qp z0j*S1LqidF((2NQ^Rn20A3f(iB{qCE+=vxSKy7#3X#tN%|RE`iJ2b4VG0?eGK` gZ|4|n2a_BeNJRL1VBJSIFJ%CrQ3JfHJz1Im05V~78UO$Q diff --git a/Images/low-pass1.png b/Images/low-pass1.png deleted file mode 100644 index 157e22ee6c81b1ba7d1c4ecccde4c416bb7ec5a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2268 zcmcJQdpy(s9>>4JqPgTUEf$J~+`e;NL*k&8(Fmc7jk(P&+guMaGyN!5ZfR7gKpXXoiOuXw6*&V7o005B1 z9(8aB05M(Ry;n-O0S=z_4B;UWZ0BMJ01YhY52B<{i&5Q=*aP)k#GFuQ1{`&F0f0m# z0Hme^z;|IObrt|(KmeF0005>40Ct@#X?L?0Hn#aYA8`OSFR%t53zhV_qdrsskn7o6 zVg>qgY5=f(6zgE;5kJ0Iaw_&uaHm7qW=%ggNKRUQuR+y!PcO}%^ve^YF{hT`0feuD zT^{`K)c1;Lwbb%AsT6UEv`F!O*_~4DvbvUsHD@hK-vac~|Djf z$?6Ej_gp+r@og>=YB5edHI@B*7BPl_`V9`4WfTwRSV6Ym=XPm9r!ggKZ~2{tKJf|7 zJh59g2hok5F9isy&9L_;{?fA#B?^dZnHs%kh7J@bHFL^*R8y(%16OS?y6M;Y1=hFI ziHQf91-#J(K`JilN!ha3@6}X~{MyCj)uF0J)j^Sv)sfWcCxbPvrPKQ-sQBpIT1eBp z1i4GPOK;0!TG@xtm&PaUOVM!9Z`J!?7+wf7FrOJ73&?QzWY8S%UPXtP5x3A zll*>tXRZ#S+x>}3e>L+Y`gq5txs)`r2`#(LA7O0?U1rZwW*J!n4=v+=7-z<&o_ywJ z5(R5`yR*#Bv{Sd2Lv6a;fA_3zbm_n?yJBeZ18if7bB5*bX{)2d*#>emSr)r2qVrNV zi`AHmy|cmnv%O)S8bg{;5qYf z^J`z2cXEPr&Z?&~t-m!EFwSVwjDq4GNA6{HRA-I3w(4*5C+$ce`E^e+vZ#)Slk%0@ zhuqun!?w>u%J%&%Y*F=)PyHJ-#Q0#c$sZt9tl2Mi)K9 zYgY9Pu=eYCp($>v^YN-RJ)kk}5<}alpm@FmNQ!AkK=cg+t z^`H3cNt(7#$f=x*jOc;O%v-c1ly%=8)G^|%MUJj~16VXZ%2vz&Wv!~wLEt%dEIBj@7 z$Ac_VP9y(p{RHYV^wLFkI1Y7^fQPU?P@u~e78(b_m7L%R*I?sVv|bmhhXZ4QzA5s1KW@L7_s7CF@4|R+ZLk~{j_awHvX{Y+icDe4IkW}_yK%%T%j7+ zs9T4(5Yy-W@yc&^kIPE(gV(3Cw+eK(?DfeJ<6{R;YMqLJ6Km&M^JsB&ZUKrtn$fb1 z(67h!7}#6_#bRY{TrHZqpn%N0uAfJ$aNq{b^lM+!yV5k)W`Yem_R+IlaFuxTA>PSw z<`)>Q_yV@1Mg#>$s3W86o$il=U7gJdMLlh*W8`j#X`&L&laAWlWz73}a>xS)Utaaq zJ#pJmIW#V%iL1eRnqnQb(eNm!jBUm2b9`iYjo3KHvSK&Gs??5pw8Sx{H$V5fkZRQ69O`+SIw@j^pRsMDSO%!DA#3h z;=iM>>fGd=xL8F1OUi!|3|d-w{s-VPcS9=L>ZZJuI0W>QWOlN7!D&}<#<23Db!*F8 z@;i-h>G!Z*H=<_a<|8&~3z`lif8zsn_vu(UZMENmKc3oB0ox`l<5 zRuN$-8i=s8y+v5qd*GMvb^HTxy@x!5-A?^R=FS;c8l8u7iMJQrn@E3QSr_;DJS~3! znGGA9G0JaPe$2$&qUz7LeLfEr#L}C@Qk?%iocXOi=UJLh&qQAY@WQFTpXTUIBN1tV zm;g$k@BmCel$jxDW{5(0piD7lrWnvfA2h>&AhXi@!G8oIqDY}Z3BmwqVu%6_O-wvc cXbj2>V~YM2Xt_GpDhvQvM^}e>dqUd30Mi2cIsgCw diff --git a/Images/multiloop.png b/Images/multiloop.png deleted file mode 100644 index 5988f88073f1a121918634deaa43e677c03938f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1674 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 diff --git a/filtersintez.cpp b/filtersintez.cpp index b6297321c3..2675b4191b 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -83,10 +83,9 @@ FilterSintez::FilterSintez(QWidget *parent) imgAFR = new QSvgWidget(":/images/AFR.svg"); imgAFR->show(); - sch_pic = new QLabel; - QPixmap pix("Images/dblquad.png"); - sch_pic->resize(pix.size()); - sch_pic->setPixmap(pix); + sch_pic = new QSvgWidget(":/images/sk-lowpass.svg"); + // QPixmap pix("Images/dblquad.png"); + sch_pic->show(); top = new QHBoxLayout; left = new QVBoxLayout; @@ -234,21 +233,23 @@ void FilterSintez::slotUpdateSchematic() { QString s; switch (cbxFilterType->currentIndex()) { - case 0 : s = "Images/dblquad.png"; + case 0 : s = ":images/sk-lowpass.svg"; break; - case 1 : s= "Images/multiloop.png"; + case 1 : if (btnHighPass->isChecked()) s = ":/images/mfb-highpass.svg"; + else s = ":/images/mfb-lowpass.svg"; break; - case 2 : if (btnHighPass->isChecked()) s = "Images/high-pass1.png"; - else s = "Images/low-pass1.png"; + case 2 : if (btnHighPass->isChecked()) s = ":/images/sk-highpass.svg"; + else s = ":/images/sk-lowpass.svg"; break; - case 3 : s = "Images/passive.png"; + case 3 : s = ":/images/mfb-lowpass.svg"; break; default: break; } - QPixmap pix(s); - sch_pic->resize(pix.size()); - sch_pic->setPixmap(pix); + sch_pic->load(s); + //QPixmap pix(s); + //sch_pic->resize(pix.size()); + //sch_pic->setPixmap(pix); } void FilterSintez::slotSwitchParameters() diff --git a/filtersintez.h b/filtersintez.h index 37d7dc029a..aca501b731 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -53,7 +53,7 @@ class FilterSintez : public QMainWindow QVBoxLayout *center; QVBoxLayout *right; - QLabel *sch_pic; + QSvgWidget *sch_pic; QWidget *zenter; diff --git a/mfb-highpass.svg b/mfb-highpass.svg new file mode 100644 index 0000000000..dfd09dd61d --- /dev/null +++ b/mfb-highpass.svg @@ -0,0 +1,407 @@ + + +Qt Svg Document +Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +OP1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V1 + + + + + + + + + + + + +R2 + + + + + + + + + + + + +R1 + + + + + + + + + + + + + +C3 + + + + + + + + + + + + + +C2 + + + + + + + + + + + + + +C1 + + + + + + + + + + + + + + + + + +output + + + + + + + + + + + + + + + + +input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mfb-lowpass.svg b/mfb-lowpass.svg new file mode 100644 index 0000000000..e96314ac8d --- /dev/null +++ b/mfb-lowpass.svg @@ -0,0 +1,404 @@ + + +Qt Svg Document +Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R3 + + + + + + + + + + + + +R2 + + + + + + + + + + + + +R1 + + + + + + + + + + + + + +C2 + + + + + + + + + + + + + + + + + + + + + +OP1 + + + + + + + + + + + + + +C1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V1 + + + + + + + + + + + + + + + + + + + +output + + + + + + + + + + + + + + + + +input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/qfiltersintez.qrc b/qfiltersintez.qrc index fcecaf6956..f0b56bd092 100644 --- a/qfiltersintez.qrc +++ b/qfiltersintez.qrc @@ -1,5 +1,9 @@ + sk-highpass.svg + sk-lowpass.svg + mfb-lowpass.svg + mfb-highpass.svg AFR.svg diff --git a/sk-highpass.svg b/sk-highpass.svg new file mode 100644 index 0000000000..f3de1a6b4a --- /dev/null +++ b/sk-highpass.svg @@ -0,0 +1,430 @@ + + +Qt Svg Document +Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +C1 + + + + + + + + + + + + + +C2 + + + + + + + + + + + + +R1 + + + + + + + + + + + + +R2 + + + + + + + + + + + + +R4 + + + + + + + + + + + + +R3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V1 + + + + + + + + + + + + + + + + + + + + + +OP1 + + + + + + + + +output + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sk-lowpass.svg b/sk-lowpass.svg new file mode 100644 index 0000000000..4c8e3812fa --- /dev/null +++ b/sk-lowpass.svg @@ -0,0 +1,430 @@ + + +Qt Svg Document +Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R4 + + + + + + + + + + + + +R3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V1 + + + + + + + + + + + + + + + + + + + + + +OP1 + + + + + + + + + + + + +R1 + + + + + + + + + + + + +R2 + + + + + + + + + + + + + +C2 + + + + + + + + + + + + + +C1 + + + + + + + + + + + + + + + + + + +input + + + + + + + + + + + + + + + + + + + +output + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fbb7ae413b8b08640b8d251228a31355a4272cf2 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 5 May 2014 10:50:28 +0400 Subject: [PATCH 49/90] Fixed random SVG schematic image stretching. Now schematic has fixed size. --- filtersintez.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 2675b4191b..a9480509d8 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -82,9 +82,14 @@ FilterSintez::FilterSintez(QWidget *parent) this->slotSwitchParameters(); imgAFR = new QSvgWidget(":/images/AFR.svg"); + QSize sz = imgAFR->size(); + sz *= 0.5; + imgAFR->setFixedSize(sz); imgAFR->show(); sch_pic = new QSvgWidget(":/images/sk-lowpass.svg"); - // QPixmap pix("Images/dblquad.png"); + sz = sch_pic->size(); + sz *= 0.5; + sch_pic->setFixedSize(sz); sch_pic->show(); top = new QHBoxLayout; @@ -124,6 +129,7 @@ FilterSintez::FilterSintez(QWidget *parent) right->addWidget(imgAFR); right->addWidget(sch_pic); + right->addStretch(); top->addLayout(left); top->addLayout(center); @@ -246,10 +252,13 @@ void FilterSintez::slotUpdateSchematic() default: break; } + QSvgRenderer *ren = new QSvgRenderer(s); + QSize sz = ren->defaultSize(); + sz *= 0.75; + delete ren; + sch_pic->load(s); - //QPixmap pix(s); - //sch_pic->resize(pix.size()); - //sch_pic->setPixmap(pix); + sch_pic->setFixedSize(sz); } void FilterSintez::slotSwitchParameters() From 34cc29e6d1d1dd4877906ad12a1c0db338256ee1 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 5 May 2014 19:00:05 +0400 Subject: [PATCH 50/90] Implemented high-pass Cauer schematic calculation --- schcauer.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/schcauer.cpp b/schcauer.cpp index 7a4bbce349..af7cd6c48b 100644 --- a/schcauer.cpp +++ b/schcauer.cpp @@ -54,7 +54,45 @@ void SchCauer::calcLowPass() void SchCauer::calcHighPass() { + float R1,R2,R3,R4,R5,C1,C2; + float Wc = 2*M_PI*Fc; + float Nst = order/2 + order%2; + float Kv1 = pow(Kv,1.0/Nst); + //qDebug()<calcFirstOrder(); } @@ -65,5 +103,5 @@ void SchCauer::createLowPassSchematic(QString &s) void SchCauer::createHighPassSchematic(QString &s) { - + createLowPassSchematic(s); } From 75488128e84553c2b6f0f649d1cb040c69f31bf6 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 5 May 2014 19:12:58 +0400 Subject: [PATCH 51/90] Added image for Cauer schematic --- cauer.svg | 604 ++++++++++++++++++++++++++++++++++++++++++++++ filtersintez.cpp | 6 +- qfiltersintez.qrc | 1 + 3 files changed, 608 insertions(+), 3 deletions(-) create mode 100644 cauer.svg diff --git a/cauer.svg b/cauer.svg new file mode 100644 index 0000000000..acf9ceee3c --- /dev/null +++ b/cauer.svg @@ -0,0 +1,604 @@ + + +Qt Svg Document +Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R1 + + + + + + + + + + + + + + + + + + + + + +OP3 + + + + + + + + + + + + + + + + + + + + + +OP2 + + + + + + + + + + + + + +C1 + + + + + + + + + + + + + + + + + + + + + +OP1 + + + + + + + + + + + + + + + + + + + + + + + +C2 + + + + + + + + + + + + +R5 + + + + + + + + + + + + +R4 + + + + + + + + + + + + +R2 + + + + + + + + + + + + +R3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +output + + + + + + + + + + + + + + + + + + + + +input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/filtersintez.cpp b/filtersintez.cpp index a9480509d8..5e88112655 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -86,9 +86,9 @@ FilterSintez::FilterSintez(QWidget *parent) sz *= 0.5; imgAFR->setFixedSize(sz); imgAFR->show(); - sch_pic = new QSvgWidget(":/images/sk-lowpass.svg"); + sch_pic = new QSvgWidget(":/images/cauer.svg"); sz = sch_pic->size(); - sz *= 0.5; + sz *= 0.75; sch_pic->setFixedSize(sz); sch_pic->show(); @@ -239,7 +239,7 @@ void FilterSintez::slotUpdateSchematic() { QString s; switch (cbxFilterType->currentIndex()) { - case 0 : s = ":images/sk-lowpass.svg"; + case 0 : s = ":images/cauer.svg"; break; case 1 : if (btnHighPass->isChecked()) s = ":/images/mfb-highpass.svg"; else s = ":/images/mfb-lowpass.svg"; diff --git a/qfiltersintez.qrc b/qfiltersintez.qrc index f0b56bd092..df284b8882 100644 --- a/qfiltersintez.qrc +++ b/qfiltersintez.qrc @@ -5,5 +5,6 @@ mfb-lowpass.svg mfb-highpass.svg AFR.svg + cauer.svg From 4dba52e017534e37fb1f17d615b6ebf169ea5a56 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 6 May 2014 19:47:12 +0400 Subject: [PATCH 52/90] Implememted components writing for Cauer filter --- filtersintez.cpp | 1 + schcauer.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 5e88112655..398a07be9e 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -192,6 +192,7 @@ void FilterSintez::slotCalcSchematic() cauer.calcFilter(); cauer.createPolesZerosList(lst); cauer.createPartList(lst); + cauer.createSchematic(s); txtResult->setText(lst.join("\n")); } diff --git a/schcauer.cpp b/schcauer.cpp index af7cd6c48b..9a32a83e0b 100644 --- a/schcauer.cpp +++ b/schcauer.cpp @@ -3,9 +3,9 @@ SchCauer::SchCauer(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) : Filter(ffunc_, type_, par) { - Nr = 5; - Nopamp = 3; - Nc = 2; + Nr1 = 5; + Nop1 = 3; + Nc1 = 2; } void SchCauer::calcLowPass() @@ -98,6 +98,56 @@ void SchCauer::calcHighPass() void SchCauer::createLowPassSchematic(QString &s) { + RC_elements stage; + int dx = 0; + int N2ord = order/2; // number of 2-nd order stages + int N1stOrd = order%2; // number of 1-st order stages + + s += "\n"; + s += "\n"; + s += "\n"; + s += "<.DC DC1 1 40 510 0 61 0 0 \"26.85\" 0 \"0.001\" 0 \"1 pA\" 0 \"1 uV\" 0 \"no\" 0 \"150\" 0 \"no\" 0 \"none\" 0 \"CroutLU\" 0>\n"; + s += "\n"; + s += "<.AC AC1 1 320 510 0 61 0 0 \"lin\" 1 \"1 Hz\" 1 \"10 kHz\" 1 \"5001\" 1 \"no\" 0>\n"; + s += "\n"; + + for (int i=1; i<=N2ord; i++) { + stage = Sections.at(i-1); + qDebug()<\n").arg(1+(i-1)*Nop1).arg(270+dx); + s += QString("\n").arg(2+(i-1)*Nop1).arg(300+dx); + s += QString("\n").arg(3+(i-1)*Nop1).arg(560+dx); + s += QString("\n").arg(1+(i-1)*Nc1).arg(330+dx).arg(C1,0,'f',3).arg(suffix1); + s += QString("\n").arg(2+(i-1)*Nc1).arg(450+dx).arg(C2,0,'f',3).arg(suffix2); + s += QString("\n").arg(1+(i-1)*Nr1).arg(180+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(2+(i-1)*Nr1).arg(410+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(3+(i-1)*Nr1).arg(440+dx).arg(stage.R3,0,'f',3); + s += QString("\n").arg(4+(i-1)*Nr1).arg(360+dx).arg(stage.R4,0,'f',3); + s += QString("\n").arg(5+(i-1)*Nr1).arg(190+dx).arg(stage.R5,0,'f',3); + s += QString("\n").arg(240+dx); + s += QString("\n").arg(250+dx); + + dx += 630; + } + + if (N1stOrd!=0) { + createFirstOrderComponentsLPF(s,Sections.last(),dx+10); + } + + s += "\n"; + s += "\n"; + dx = 0; + s += "<80 220 140 220 \"in\" 120 170 0 \"\">\n"; + s += "<80 220 80 260 \"\" 0 0 0 \"\">\n"; + + for (int i=1; i<=N2ord; i++) { + + } + + s += "\n"; } From d9cb376e2a9d874f0f1e60c865af47cc1cbd54be Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 6 May 2014 20:31:59 +0400 Subject: [PATCH 53/90] Implememted writing schematic for even order Cauer filters. Odd order not works. --- schcauer.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/schcauer.cpp b/schcauer.cpp index 9a32a83e0b..ce96771aa9 100644 --- a/schcauer.cpp +++ b/schcauer.cpp @@ -130,7 +130,7 @@ void SchCauer::createLowPassSchematic(QString &s) s += QString("\n").arg(240+dx); s += QString("\n").arg(250+dx); - dx += 630; + dx += 580; } if (N1stOrd!=0) { @@ -144,7 +144,52 @@ void SchCauer::createLowPassSchematic(QString &s) s += "<80 220 80 260 \"\" 0 0 0 \"\">\n"; for (int i=1; i<=N2ord; i++) { + if (i!=1) { + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(dx+30).arg(140+dx); + } + s += QString("<%1 370 %2 370 \"\" 0 0 0 \"\">\n").arg(500+dx).arg(610+dx); + s += QString("<%1 220 %2 220 \"\" 0 0 0 \"\">\n").arg(210+dx).arg(220+dx); + s += QString("<%1 280 %2 370 \"\" 0 0 0 \"\">\n").arg(500+dx).arg(500+dx); + s += QString("<%1 280 %2 280 \"\" 0 0 0 \"\">\n").arg(500+dx).arg(530+dx); + s += QString("<%1 260 %2 260 \"\" 0 0 0 \"\">\n").arg(600+dx).arg(610+dx); + s += QString("<%1 260 %2 370 \"\" 0 0 0 \"\">\n").arg(610+dx).arg(610+dx); + s += QString("<%1 240 %2 240 \"\" 0 0 0 \"\">\n").arg(440+dx).arg(480+dx); + s += QString("<%1 400 %2 400 \"\" 0 0 0 \"\">\n").arg(340+dx).arg(420+dx); + s += QString("<%1 380 %2 380 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(260+dx); + s += QString("<%1 380 %2 380 \"\" 0 0 0 \"\">\n").arg(260+dx).arg(270+dx); + s += QString("<%1 150 %2 220 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); + s += QString("<%1 150 %2 150 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(300+dx); + s += QString("<%1 240 %2 240 \"\" 0 0 0 \"\">\n").arg(310+dx).arg(380+dx); + s += QString("<%1 260 %2 290 \"\" 0 0 0 \"\">\n").arg(240+dx).arg(240+dx); + s += QString("<%1 220 %2 220 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(240+dx); + s += QString("<%1 420 %2 420 \"\" 0 0 0 \"\">\n").arg(250+dx).arg(270+dx); + s += QString("<%1 420 %2 440 \"\" 0 0 0 \"\">\n").arg(250+dx).arg(250+dx); + if ((2*i)==order) { + s += QString("<%1 110 %2 260 \"out\" %3 160 101 \"\">\n").arg(610+dx).arg(610+dx).arg(540+dx); + } else { + s += QString("<%1 110 %2 260 \"\" 0 0 0 \"\">\n").arg(610+dx).arg(610+dx); + } + s += QString("<%1 110 %2 110 \"\" 0 0 0 \"\">\n").arg(470+dx).arg(610+dx); + s += QString("<%1 110 %2 150 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(220+dx); + s += QString("<%1 110 %2 110 \"\" 0 0 0 \"\">\n").arg(220+dx).arg(410+dx); + s += QString("<%1 220 %2 220 \"\" 0 0 0 \"\">\n").arg(140+dx).arg(150+dx); + s += QString("<%1 220 %2 260 \"\" 0 0 0 \"\">\n").arg(140+dx).arg(140+dx); + s += QString("<%1 260 %2 380 \"\" 0 0 0 \"\">\n").arg(140+dx).arg(140+dx); + s += QString("<%1 380 %2 380 \"\" 0 0 0 \"\">\n").arg(140+dx).arg(160+dx); + s += QString("<%1 240 %2 240 \"\" 0 0 0 \"\">\n").arg(480+dx).arg(530+dx); + s += QString("<%1 240 %2 400 \"\" 0 0 0 \"\">\n").arg(480+dx).arg(480+dx); + s += QString("<%1 320 %2 400 \"\" 0 0 0 \"\">\n").arg(420+dx).arg(420+dx); + s += QString("<%1 320 %2 320 \"\" 0 0 0 \"\">\n").arg(390+dx).arg(420+dx); + s += QString("<%1 320 %2 380 \"\" 0 0 0 \"\">\n").arg(260+dx).arg(260+dx); + s += QString("<%1 320 %2 320 \"\" 0 0 0 \"\">\n").arg(260+dx).arg(330+dx); + s += QString("<%1 150 %2 150 \"\" 0 0 0 \"\">\n").arg(360+dx).arg(380+dx); + s += QString("<%1 150 %2 240 \"\" 0 0 0 \"\">\n").arg(380+dx).arg(380+dx); + + dx +=580; + } + if (N1stOrd!=0) { + createFirstOrderWires(s,dx+10,260); } s += "\n"; From 767a751943ca27e8ac77f82db66ff4c7683c7d5b Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 6 May 2014 20:42:54 +0400 Subject: [PATCH 54/90] Implemented odd order Cauer filter schematic writing --- schcauer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schcauer.cpp b/schcauer.cpp index ce96771aa9..e1f98e93e1 100644 --- a/schcauer.cpp +++ b/schcauer.cpp @@ -134,7 +134,7 @@ void SchCauer::createLowPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderComponentsLPF(s,Sections.last(),dx+10); + createFirstOrderComponentsLPF(s,Sections.last(),dx+80); } s += "\n"; @@ -189,7 +189,7 @@ void SchCauer::createLowPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderWires(s,dx+10,260); + createFirstOrderWires(s,dx+80,260); } s += "\n"; From 66b0cf0b286fb2d7983f7cbfb909b6412b735e65 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 7 May 2014 09:50:15 +0400 Subject: [PATCH 55/90] Implemented high-pass cauer schematic writing --- schcauer.cpp | 23 ++++++++++++++++------- schcauer.h | 3 +++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/schcauer.cpp b/schcauer.cpp index e1f98e93e1..097f7efe69 100644 --- a/schcauer.cpp +++ b/schcauer.cpp @@ -97,6 +97,16 @@ void SchCauer::calcHighPass() void SchCauer::createLowPassSchematic(QString &s) +{ + createGenericSchematic(s); +} + +void SchCauer::createHighPassSchematic(QString &s) +{ + createGenericSchematic(s); +} + +void SchCauer::createGenericSchematic(QString &s) { RC_elements stage; int dx = 0; @@ -134,7 +144,12 @@ void SchCauer::createLowPassSchematic(QString &s) } if (N1stOrd!=0) { - createFirstOrderComponentsLPF(s,Sections.last(),dx+80); + if (ftype==Filter::LowPass) { + createFirstOrderComponentsLPF(s,Sections.last(),dx+80); + } else if (ftype==Filter::HighPass) { + createFirstOrderComponentsHPF(s,Sections.last(),dx+80); + } + } s += "\n"; @@ -193,10 +208,4 @@ void SchCauer::createLowPassSchematic(QString &s) } s += "\n"; - -} - -void SchCauer::createHighPassSchematic(QString &s) -{ - createLowPassSchematic(s); } diff --git a/schcauer.h b/schcauer.h index 20d8b34ae1..689e721c1d 100644 --- a/schcauer.h +++ b/schcauer.h @@ -9,6 +9,9 @@ class SchCauer : public Filter // Cauer 2-order section { +private: + void createGenericSchematic(QString &s); + protected: void calcHighPass(); From 583e4b31d6547c72fbaaee70b1e7947467e6dfa7 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 7 May 2014 10:20:17 +0400 Subject: [PATCH 56/90] If calculation of filter is failed poles and zeros list and part list are always created --- filtersintez.cpp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 398a07be9e..aae603b937 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -185,15 +185,23 @@ void FilterSintez::slotCalcSchematic() ftyp = Filter::BandStop; } + switch (cbxFilterType->currentIndex()) { case 0 : { QString s; - SchCauer cauer(ffunc,ftyp,par); - cauer.calcFilter(); - cauer.createPolesZerosList(lst); - cauer.createPartList(lst); - cauer.createSchematic(s); - txtResult->setText(lst.join("\n")); + if (((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) { + SchCauer cauer(ffunc,ftyp,par); + bool ok = cauer.calcFilter(); + cauer.createPolesZerosList(lst); + cauer.createPartList(lst); + if (ok) { + cauer.createSchematic(s); + } + txtResult->setText(lst.join("\n")); + } else { + errorMessage(tr("Unable to use Cauer section for Chebyshev or Butterworth \n" + "frequency response. Try to use another topology.")); + } } break; @@ -201,11 +209,12 @@ void FilterSintez::slotCalcSchematic() QString s; if (!((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) { MFBfilter mfb(ffunc,ftyp,par); - if (mfb.calcFilter()) { - mfb.createPolesZerosList(lst); - mfb.createPartList(lst); + bool ok = mfb.calcFilter(); + mfb.createPolesZerosList(lst); + mfb.createPartList(lst); + txtResult->setText(lst.join("\n")); + if (ok) { mfb.createSchematic(s); - txtResult->setText(lst.join("\n")); } else { errorMessage(tr("Unable to implement filter with such parameters and topology \n" "Change parapeters and/or topology and try again!")); @@ -219,11 +228,12 @@ void FilterSintez::slotCalcSchematic() case 2 : { QString s; SallenKey sk(ffunc,ftyp,par); - if (sk.calcFilter()) { - sk.createPolesZerosList(lst); - sk.createPartList(lst); + bool ok = sk.calcFilter(); + sk.createPolesZerosList(lst); + sk.createPartList(lst); + txtResult->setText(lst.join("\n")); + if (ok) { sk.createSchematic(s); - txtResult->setText(lst.join("\n")); } else { errorMessage(tr("Unable to implement filter with such parameters and topology \n" "Change parapeters and/or topology and try again!")); From 08ca4342e2db5d604a65c2185ce0f5b870bc08a9 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 7 May 2014 14:53:28 +0400 Subject: [PATCH 57/90] Results text editor was moved to bottom of main window --- filtersintez.cpp | 17 ++++++++++++----- filtersintez.h | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index aae603b937..470fca4e40 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -13,7 +13,7 @@ FilterSintez::FilterSintez(QWidget *parent) QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); - lblInputData = new QLabel(tr("Входные данные")); + //lblInputData = new QLabel(tr("Входные данные")); lblA1 = new QLabel(tr("Затухание в полосе пропускания, Ap")); lblA2 = new QLabel(tr("Мин. затухание в полосе задерживания, As")); lblF1 = new QLabel(tr("Частота среза фильтра, Fc (Гц)")); @@ -97,7 +97,7 @@ FilterSintez::FilterSintez(QWidget *parent) center = new QVBoxLayout; right = new QVBoxLayout; - left->addWidget(lblInputData); + //left->addWidget(lblInputData); left->addWidget(lblA1); left->addWidget(edtA1); left->addWidget(lblA2); @@ -114,9 +114,9 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(cbxFilterFunc); - center->addWidget(lblResult); + /*center->addWidget(lblResult); center->addWidget(txtResult); - txtResult->setMinimumWidth(400); + txtResult->setMinimumWidth(400);*/ txtResult->setReadOnly(true); left->addWidget(lblSch); @@ -135,9 +135,16 @@ FilterSintez::FilterSintez(QWidget *parent) top->addLayout(center); top->addLayout(right); + top1 = new QVBoxLayout; + top1->addLayout(top); + QSplitter *sp1 = new QSplitter; + top1->addWidget(sp1); + top1->addWidget(txtResult); + txtResult->setMinimumHeight(100); + zenter = new QWidget; this->setCentralWidget(zenter); - zenter->setLayout(top); + zenter->setLayout(top1); } FilterSintez::~FilterSintez() diff --git a/filtersintez.h b/filtersintez.h index aca501b731..1f0e2e82a5 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -52,6 +52,7 @@ class FilterSintez : public QMainWindow QVBoxLayout *left; QVBoxLayout *center; QVBoxLayout *right; + QVBoxLayout *top1; QSvgWidget *sch_pic; From f13032c07b7fef2f8bde7a8f5ae4041d0fda1f20 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 7 May 2014 20:23:13 +0400 Subject: [PATCH 58/90] Fixed images size fitting and added hig-pass filter response image --- filtersintez.cpp | 15 +- high-pass.svg | 405 ++++++++++++++++++++++++++++++++++++++++++++++ qfiltersintez.qrc | 1 + 3 files changed, 416 insertions(+), 5 deletions(-) create mode 100644 high-pass.svg diff --git a/filtersintez.cpp b/filtersintez.cpp index 470fca4e40..2b641dd2a2 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -83,12 +83,17 @@ FilterSintez::FilterSintez(QWidget *parent) imgAFR = new QSvgWidget(":/images/AFR.svg"); QSize sz = imgAFR->size(); - sz *= 0.5; + sz *= 0.4; imgAFR->setFixedSize(sz); imgAFR->show(); - sch_pic = new QSvgWidget(":/images/cauer.svg"); - sz = sch_pic->size(); - sz *= 0.75; + + QString s1 = ":/images/cauer.svg"; + QSvgRenderer *ren = new QSvgRenderer(s1); + sz = ren->defaultSize(); + sz *= 0.65; + delete ren; + + sch_pic = new QSvgWidget(s1); sch_pic->setFixedSize(sz); sch_pic->show(); @@ -272,7 +277,7 @@ void FilterSintez::slotUpdateSchematic() QSvgRenderer *ren = new QSvgRenderer(s); QSize sz = ren->defaultSize(); - sz *= 0.75; + sz *= 0.65; delete ren; sch_pic->load(s); diff --git a/high-pass.svg b/high-pass.svg new file mode 100644 index 0000000000..8310c97922 --- /dev/null +++ b/high-pass.svg @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + Rp + + + Fc + + + + Fs + + + As + K (dB) + F (Hz) + 0 + + + + + + Ap + + + + + + + + + + + + + + АЧХ фильтра + + + diff --git a/qfiltersintez.qrc b/qfiltersintez.qrc index df284b8882..d30e6821c5 100644 --- a/qfiltersintez.qrc +++ b/qfiltersintez.qrc @@ -6,5 +6,6 @@ mfb-highpass.svg AFR.svg cauer.svg + high-pass.svg From 048041844ad8b775deae74a7be40b63a96eb8a57 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 8 May 2014 11:35:23 +0400 Subject: [PATCH 59/90] Radio button group for filter type selection replaced by Combo-box --- filtersintez.cpp | 117 ++++++++++++++++++++++++++++------------------- filtersintez.h | 9 +++- 2 files changed, 78 insertions(+), 48 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 2b641dd2a2..2812139cb9 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -10,6 +10,7 @@ FilterSintez::FilterSintez(QWidget *parent) { Nfil = 4; Fc = 1000; + ftyp = Filter::NoFilter; QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); @@ -57,19 +58,16 @@ FilterSintez::FilterSintez(QWidget *parent) lblSch = new QLabel(tr("Схемная реализация фильтра")); - btnHighPass = new QRadioButton(tr("ФВЧ")); - btnLowPass = new QRadioButton(tr("ФНЧ")); - btnBandPass = new QRadioButton(tr("Band-pass")); - btnBandStop = new QRadioButton(tr("Band-stop")); - QButtonGroup *grp1 = new QButtonGroup; - grp1->addButton(btnHighPass); - grp1->addButton(btnLowPass); - grp1->addButton(btnBandPass); - grp1->addButton(btnBandStop); - btnBandPass->setDisabled(true); - btnBandStop->setDisabled(true); - btnLowPass->setChecked(true); - connect(grp1,SIGNAL(buttonClicked(int)),this,SLOT(slotUpdateSchematic())); + lblResp = new QLabel(tr("Filter type:")); + cbxResponse = new QComboBox; + QStringList lst3; + lst3<addItems(lst3); + connect(cbxResponse,SIGNAL(),this,SLOT(slotUpdtaeResponse())); + connect(cbxResponse,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); cbxFilterType = new QComboBox; QStringList lst; @@ -115,22 +113,21 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(edtPassbRpl); left->addWidget(lblKv); left->addWidget(edtKv); - left->addWidget(lblTyp); - left->addWidget(cbxFilterFunc); - - - /*center->addWidget(lblResult); - center->addWidget(txtResult); - txtResult->setMinimumWidth(400);*/ - txtResult->setReadOnly(true); - - left->addWidget(lblSch); - left->addWidget(btnLowPass); - left->addWidget(btnHighPass); - left->addWidget(btnBandPass); - left->addWidget(btnBandStop); - left->addWidget(cbxFilterType); + QHBoxLayout *l3 = new QHBoxLayout; + l3->addWidget(lblTyp); + l3->addWidget(cbxFilterFunc); + left->addLayout(l3); + + QHBoxLayout *l1 = new QHBoxLayout; + l1->addWidget(lblResp); + l1->addWidget(cbxResponse); + left->addLayout(l1); + QHBoxLayout *l2 = new QHBoxLayout; + l2->addWidget(lblSch); + l2->addWidget(cbxFilterType); + left->addLayout(l2); left->addWidget(btnCalcSchematic); + left->addStretch(); right->addWidget(imgAFR); right->addWidget(sch_pic); @@ -144,8 +141,9 @@ FilterSintez::FilterSintez(QWidget *parent) top1->addLayout(top); QSplitter *sp1 = new QSplitter; top1->addWidget(sp1); + txtResult->setReadOnly(true); top1->addWidget(txtResult); - txtResult->setMinimumHeight(100); + txtResult->setMinimumHeight(180); zenter = new QWidget; this->setCentralWidget(zenter); @@ -186,18 +184,21 @@ void FilterSintez::slotCalcSchematic() break; } - Filter::FType ftyp = Filter::NoFilter; - if (btnHighPass->isChecked()) { - ftyp = Filter::HighPass; - } else if (btnLowPass->isChecked()) { - ftyp = Filter::LowPass; - } else if (btnBandPass->isChecked()) { - ftyp = Filter::BandPass; - } else if (btnBandStop->isChecked()) { - ftyp = Filter::BandStop; - } + switch (cbxResponse->currentIndex()) { + case 0 : ftyp = Filter::LowPass; + break; + case 1 : ftyp = Filter::HighPass; + break; + case 2 : ftyp = Filter::BandPass; + break; + case 3 : ftyp = Filter::BandStop; + break; + default: ftyp = Filter::NoFilter; + break; + } + switch (cbxFilterType->currentIndex()) { case 0 : { QString s; @@ -258,21 +259,45 @@ void FilterSintez::slotCalcSchematic() } } +void FilterSintez::slotUpdateResponse() +{ + switch (cbxResponse->currentIndex()) { + case 0 : ftyp = Filter::LowPass; + break; + case 1 : ftyp = Filter::HighPass; + break; + case 2 : ftyp = Filter::BandPass; + break; + case 3 : ftyp = Filter::BandStop; + break; + default: ftyp = Filter::NoFilter; + break; + } +} + void FilterSintez::slotUpdateSchematic() { + slotUpdateResponse(); QString s; switch (cbxFilterType->currentIndex()) { case 0 : s = ":images/cauer.svg"; break; - case 1 : if (btnHighPass->isChecked()) s = ":/images/mfb-highpass.svg"; - else s = ":/images/mfb-lowpass.svg"; - break; - case 2 : if (btnHighPass->isChecked()) s = ":/images/sk-highpass.svg"; - else s = ":/images/sk-lowpass.svg"; + case 1 : if (ftyp==Filter::HighPass) { + s = ":/images/mfb-highpass.svg"; + } else if (ftyp==Filter::LowPass) { + s = ":/images/mfb-lowpass.svg"; + } break; + case 2 : if (ftyp==Filter::HighPass) { + s = ":/images/sk-highpass.svg"; + } else if (ftyp==Filter::LowPass) { + s = ":/images/sk-lowpass.svg"; + } + break; case 3 : s = ":/images/mfb-lowpass.svg"; - break; - default: break; + break; + default: + break; } QSvgRenderer *ren = new QSvgRenderer(s); diff --git a/filtersintez.h b/filtersintez.h index 1f0e2e82a5..57d739bb31 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -5,6 +5,7 @@ #include #include #include +#include "filter.h" class FilterSintez : public QMainWindow { @@ -20,6 +21,7 @@ class FilterSintez : public QMainWindow QLabel *lblKv; QLabel *lblRpl1; QLabel *lblRpl2; + QLabel *lblResp; QLineEdit *edtA1; // passband attenuation A1 QLineEdit *edtA2; // stopband attenuation A2 @@ -38,12 +40,13 @@ class FilterSintez : public QMainWindow QSvgWidget *imgAFR; QLabel *lblSch; - QRadioButton *btnLowPass; + /*QRadioButton *btnLowPass; QRadioButton *btnHighPass; QRadioButton *btnBandPass; - QRadioButton *btnBandStop; + QRadioButton *btnBandStop;*/ QComboBox *cbxFilterType; + QComboBox *cbxResponse; QPushButton *btnElements; //QPushButton *btnPassive; @@ -68,10 +71,12 @@ class FilterSintez : public QMainWindow QVector coeffB; QVector coeffC; + Filter::FType ftyp; private slots: void slotUpdateSchematic(); + void slotUpdateResponse(); void slotCalcSchematic(); void slotSwitchParameters(); From a9c4790ba350fe354e834736f5b875940c7ed8a7 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 8 May 2014 11:43:20 +0400 Subject: [PATCH 60/90] Frequency response image for hi-pass filter added to main-window --- filtersintez.cpp | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 2812139cb9..789a44c106 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -79,14 +79,17 @@ FilterSintez::FilterSintez(QWidget *parent) connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); this->slotSwitchParameters(); - imgAFR = new QSvgWidget(":/images/AFR.svg"); - QSize sz = imgAFR->size(); - sz *= 0.4; + QString s1 = ":/images/AFR.svg"; + QSvgRenderer *ren = new QSvgRenderer(s1); + QSize sz = ren->defaultSize(); + sz *= 1.1; + delete ren; + imgAFR = new QSvgWidget(s1); imgAFR->setFixedSize(sz); imgAFR->show(); - QString s1 = ":/images/cauer.svg"; - QSvgRenderer *ren = new QSvgRenderer(s1); + s1 = ":/images/cauer.svg"; + ren = new QSvgRenderer(s1); sz = ren->defaultSize(); sz *= 0.65; delete ren; @@ -261,10 +264,15 @@ void FilterSintez::slotCalcSchematic() void FilterSintez::slotUpdateResponse() { + QString s = ":/images/AFR.svg"; + switch (cbxResponse->currentIndex()) { - case 0 : ftyp = Filter::LowPass; + case 0 : + s = ":/images/AFR.svg"; + ftyp = Filter::LowPass; break; - case 1 : ftyp = Filter::HighPass; + case 1 : s = ":/images/high-pass.svg"; + ftyp = Filter::HighPass; break; case 2 : ftyp = Filter::BandPass; break; @@ -273,6 +281,14 @@ void FilterSintez::slotUpdateResponse() default: ftyp = Filter::NoFilter; break; } + + QSvgRenderer *ren = new QSvgRenderer(s); + QSize sz = ren->defaultSize(); + sz *= 1.1; + delete ren; + + imgAFR->load(s); + imgAFR->setFixedSize(sz); } void FilterSintez::slotUpdateSchematic() From dd6b14b39180aaf05a363eb76813dc776e063c97 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 8 May 2014 19:04:11 +0400 Subject: [PATCH 61/90] Fixed incorrect salle-key topology calculation if compiled with MinGW --- sallenkey.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sallenkey.cpp b/sallenkey.cpp index 12e42e9f5a..b6cdc5ec5b 100644 --- a/sallenkey.cpp +++ b/sallenkey.cpp @@ -30,7 +30,7 @@ void SallenKey::calcLowPass() C2 = 10 / Fc; C1 = (B*B+4*C*(Kv1-1))*C2/(4*C); - R1 = 2/(Wc*(B*C2+sqrt((B*B + 4*C*(Kv1-1))*(C2*C2)-4*C*C1*C2))); + R1 = 2/(Wc*(B*C2+sqrt((B*B + 4*C*(Kv1-1))*C2*C2-4*C*C1*C2))); R2 = 1/(C*C1*C2*R1*Wc*Wc); if (Kv != 1.0) { From 5e55f51a79d467ad510ad6dab60e2de9165e390a Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 9 May 2014 13:45:21 +0400 Subject: [PATCH 62/90] Fixed FsaddItems(lst3); - connect(cbxResponse,SIGNAL(),this,SLOT(slotUpdtaeResponse())); + connect(cbxResponse,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateResponse())); connect(cbxResponse,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); cbxFilterType = new QComboBox; From 8bc830ba063c847c8e410c799a72a04f42d0b07e Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 9 May 2014 13:59:36 +0400 Subject: [PATCH 63/90] Fixed odd order high-pass filter calculation --- filter.cpp | 10 ++++++++-- mfbfilter.cpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/filter.cpp b/filter.cpp index c242c9d111..710a5a9be8 100644 --- a/filter.cpp +++ b/filter.cpp @@ -95,7 +95,7 @@ void Filter::calcFirstOrder() { if (order%2 != 0) { - float R2,R3; + float R1, R2,R3; int k = order/2 + 1; float Wc = 2*M_PI*Fc; @@ -104,7 +104,13 @@ void Filter::calcFirstOrder() //float C = re*re + im*im; float C = -re; float C1 = 10/Fc; - float R1 = 1.0/(Wc*C*C1); + + if (ftype==Filter::HighPass) { + R1 = 1.0*C/(Wc*C1); + } else { + R1 = 1.0/(Wc*C*C1); + } + qDebug()<\n").arg(200+dx); s += QString("\n").arg(360+dx); s += QString("\n").arg(1+(i-1)*Nop1).arg(390+dx); - s += QString("\n").arg(1+(i-1)*Nc1).arg(200+dx).arg(stage.R1,0,'f',3); - s += QString("\n").arg(2+(i-1)*Nc1).arg(320+dx).arg(stage.R2,0,'f',3); + s += QString("\n").arg(1+(i-1)*Nr1).arg(200+dx).arg(stage.R1,0,'f',3); + s += QString("\n").arg(2+(i-1)*Nr1).arg(320+dx).arg(stage.R2,0,'f',3); s += QString("\n").arg(1+(i-1)*Nc1).arg(200+dx).arg(C1,0,'f',3).arg(suffix1); s += QString("\n").arg(2+(i-1)*Nc1).arg(150+dx).arg(C2,0,'f',3).arg(suffix2); s += QString("\n").arg(3+(i-1)*Nc1).arg(250+dx).arg(C1,0,'f',3).arg(suffix1); From 8f66ceb970e4f459539fc68b7938c7c9190c1075 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 13 May 2014 09:57:21 +0400 Subject: [PATCH 64/90] Added controls to main window for user defined transfer functions --- filter.h | 2 +- filtersintez.cpp | 32 +++++++++++++++++++++++++++++++- filtersintez.h | 2 ++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/filter.h b/filter.h index aeff270eec..fa1f3601be 100644 --- a/filter.h +++ b/filter.h @@ -30,7 +30,7 @@ class Filter public: enum FType {HighPass, LowPass, BandPass, BandStop, NoFilter}; - enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc}; + enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc, User}; private: void besselCoefficients(); diff --git a/filtersintez.cpp b/filtersintez.cpp index e10db35542..3f5b40c1f9 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -46,10 +46,15 @@ FilterSintez::FilterSintez(QWidget *parent) lst2<addItems(lst2); connect(cbxFilterFunc,SIGNAL(currentIndexChanged(int)),this,SLOT(slotSwitchParameters())); + btnDefineTransferFunc = new QPushButton(tr("Manually define transfer function")); + btnDefineTransferFunc->setEnabled(false); + connect(btnDefineTransferFunc,SIGNAL(clicked()),this,SLOT(slotDefineTransferFunc())); + btnCalcSchematic = new QPushButton(tr("Рассчитать элементы схемы фильтра")); connect(btnCalcSchematic,SIGNAL(clicked()),SLOT(slotCalcSchematic())); @@ -121,6 +126,8 @@ FilterSintez::FilterSintez(QWidget *parent) l3->addWidget(cbxFilterFunc); left->addLayout(l3); + left->addWidget(btnDefineTransferFunc); + QHBoxLayout *l1 = new QHBoxLayout; l1->addWidget(lblResp); l1->addWidget(cbxResponse); @@ -183,6 +190,8 @@ void FilterSintez::slotCalcSchematic() break; case 3 : ffunc = Filter::Cauer; break; + case 4 : ffunc = Filter::User; + break; default: ffunc = Filter::NoFunc; break; } @@ -341,6 +350,27 @@ void FilterSintez::slotSwitchParameters() } else { cbxFilterType->setDisabled(false); } + + if ((cbxFilterFunc->currentIndex()==4)) { + btnDefineTransferFunc->setEnabled(true); + edtF2->setEnabled(false); + edtPassbRpl->setEnabled(false); + edtA1->setEnabled(false); + edtA2->setEnabled(false); + edtKv->setEnabled(false); + } else { + btnDefineTransferFunc->setEnabled(false); + edtF2->setEnabled(true); + edtPassbRpl->setEnabled(true); + edtA1->setEnabled(true); + edtA2->setEnabled(true); + edtKv->setEnabled(true); + } +} + +void FilterSintez::slotDefineTransferFunc() +{ + } void FilterSintez::errorMessage(QString str) diff --git a/filtersintez.h b/filtersintez.h index 57d739bb31..413e8f9313 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -33,6 +33,7 @@ class FilterSintez : public QMainWindow QComboBox *cbxFilterFunc; QPushButton *btnCalcSchematic; + QPushButton *btnDefineTransferFunc; QLabel *lblResult; QTextEdit *txtResult; @@ -79,6 +80,7 @@ private slots: void slotUpdateResponse(); void slotCalcSchematic(); void slotSwitchParameters(); + void slotDefineTransferFunc(); public: FilterSintez(QWidget *parent = 0); From 1c06027084bb478e5db1ad8426ef71e0e6c0da13 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 14 May 2014 19:38:36 +0400 Subject: [PATCH 65/90] Started user defined transfer function poles and zeros calcultion implementation --- filter.cpp | 21 +++++++++++++++++++++ filter.h | 1 + 2 files changed, 22 insertions(+) diff --git a/filter.cpp b/filter.cpp index 710a5a9be8..633009fda2 100644 --- a/filter.cpp +++ b/filter.cpp @@ -1,4 +1,5 @@ #include "filter.h" +#include "qf_poly.h" Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) { @@ -59,6 +60,7 @@ bool Filter::calcFilter() break; case Filter::InvChebyshev : calcInvChebyshev(); break; + case Filter::User : calcUserTrFunc(); default : return false; break; } @@ -442,3 +444,22 @@ void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 Poles.append(std::complex(re,-im)); } } + +void Filter::calcUserTrFunc() +{ + long double a[3]={1,2,1}; + long double b[3]={2,2,1}; + + + qf_poly Numenator(2,a); + qf_poly Denomenetor(2,b); + + Numenator.to_roots(); + Denomenetor.to_roots(); + + Numenator.disp_c(); + Denomenetor.disp_c(); + + Numenator.roots_to_complex(Zeros); + Denomenetor.roots_to_complex(Poles); +} diff --git a/filter.h b/filter.h index fa1f3601be..f149f02a38 100644 --- a/filter.h +++ b/filter.h @@ -54,6 +54,7 @@ class Filter void calcInvChebyshev(); void calcCauer(); void calcBessel(); + void calcUserTrFunc(); bool checkRCL(); // Checks RCL values. Are one of them NaN or not? void createFirstOrderComponentsHPF(QString &s,RC_elements stage, int dx); From e201b42db79a58a3210b34f24c37f8a1bcb04062 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 15 May 2014 16:51:10 +0400 Subject: [PATCH 66/90] Added stub for transfer function definition dialog --- QFilterSintez.pro | 6 ++++-- transferfuncdialog.cpp | 6 ++++++ transferfuncdialog.h | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 transferfuncdialog.cpp create mode 100644 transferfuncdialog.h diff --git a/QFilterSintez.pro b/QFilterSintez.pro index 188f0912a1..2c07edafa5 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -18,7 +18,8 @@ SOURCES += main.cpp\ sallenkey.cpp \ mfbfilter.cpp \ qf_poly.cpp \ - schcauer.cpp + schcauer.cpp \ + transferfuncdialog.cpp HEADERS += filtersintez.h \ filter.h \ @@ -26,7 +27,8 @@ HEADERS += filtersintez.h \ mfbfilter.h \ qf_poly.h \ qf_matrix.h \ - schcauer.h + schcauer.h \ + transferfuncdialog.h RESOURCES += \ qfiltersintez.qrc diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp new file mode 100644 index 0000000000..d8abc23f61 --- /dev/null +++ b/transferfuncdialog.cpp @@ -0,0 +1,6 @@ +#include "transferfuncdialog.h" + +TransferFuncDialog::TransferFuncDialog(QWidget *parent) : + QDialog(parent) +{ +} diff --git a/transferfuncdialog.h b/transferfuncdialog.h new file mode 100644 index 0000000000..6c656fd386 --- /dev/null +++ b/transferfuncdialog.h @@ -0,0 +1,19 @@ +#ifndef TRANSFERFUNCDIALOG_H +#define TRANSFERFUNCDIALOG_H + +#include +#include + +class TransferFuncDialog : public QDialog +{ + Q_OBJECT +public: + explicit TransferFuncDialog(QWidget *parent = 0); + +signals: + +public slots: + +}; + +#endif // TRANSFERFUNCDIALOG_H From 6d58cfdf9a95c5816644374d90a384a3ea3784bc Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 15 May 2014 17:15:36 +0400 Subject: [PATCH 67/90] Started implementation of transfer function dialog --- filtersintez.cpp | 5 ++++- transferfuncdialog.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++ transferfuncdialog.h | 16 +++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 3f5b40c1f9..311fb4c9a5 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -2,6 +2,7 @@ #include "sallenkey.h" #include "mfbfilter.h" #include "schcauer.h" +#include "transferfuncdialog.h" #include @@ -370,7 +371,9 @@ void FilterSintez::slotSwitchParameters() void FilterSintez::slotDefineTransferFunc() { - + TransferFuncDialog *trfuncdlg = new TransferFuncDialog(this); + trfuncdlg->exec(); + delete trfuncdlg; } void FilterSintez::errorMessage(QString str) diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index d8abc23f61..33070ae08d 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -3,4 +3,48 @@ TransferFuncDialog::TransferFuncDialog(QWidget *parent) : QDialog(parent) { + lblB = new QLabel(tr("Numenator b[i]=")); + lblA = new QLabel(tr("Denomenator a[i]=")); + + tblA = new QTableWidget; + QStringList head1; + head1<setColumnCount(head1.count()); + tblA->setRowCount(50); + tblA->setHorizontalHeaderLabels(head1); + tblB = new QTableWidget; + QStringList head2; + head2<setColumnCount(head2.count()); + tblB->setRowCount(50); + tblB->setHorizontalHeaderLabels(head2); + + btnAccept = new QPushButton(tr("Accept")); + connect(btnAccept,SIGNAL(clicked()),this,SLOT(accept())); + btnCancel = new QPushButton(tr("Cancel")); + connect(btnCancel,SIGNAL(clicked()),this,SLOT(reject())); + + low1 = new QVBoxLayout; + low1->addWidget(lblB); + low1->addWidget(tblB); + + low2 = new QVBoxLayout; + low2->addWidget(lblA); + low2->addWidget(tblA); + + low3 = new QHBoxLayout; + low3->addWidget(btnAccept); + low3->addWidget(btnCancel); + + top = new QHBoxLayout; + top->addLayout(low1); + top->addLayout(low2); + + top1 = new QVBoxLayout; + top1->addLayout(top); + top1->addLayout(low3); + + + this->setLayout(top1); + } diff --git a/transferfuncdialog.h b/transferfuncdialog.h index 6c656fd386..c141f7fd06 100644 --- a/transferfuncdialog.h +++ b/transferfuncdialog.h @@ -7,6 +7,22 @@ class TransferFuncDialog : public QDialog { Q_OBJECT + +private: + QLabel *lblA; + QLabel *lblB; + QTableWidget *tblA; + QTableWidget *tblB; + + QPushButton *btnAccept; + QPushButton *btnCancel; + + QHBoxLayout *top; + QVBoxLayout *top1; + QVBoxLayout *low1; + QVBoxLayout *low2; + QHBoxLayout *low3; + public: explicit TransferFuncDialog(QWidget *parent = 0); From 4cf6d04392ec97921af13b8033f48d62f75d3753 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 16 May 2014 10:55:17 +0400 Subject: [PATCH 68/90] Added getCoeffs() function to Transfe --- transferfuncdialog.cpp | 18 ++++++++++++++++++ transferfuncdialog.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index 33070ae08d..b60451c416 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -48,3 +48,21 @@ TransferFuncDialog::TransferFuncDialog(QWidget *parent) : this->setLayout(top1); } + +void TransferFuncDialog::getCoeffs(QVector &a, QVector &b) +{ + a.clear(); + b.clear(); + + for (int i=0;irowCount();i++) { + QString str = tblA->item(i,0)->text(); + if (str.isEmpty()) break; + a.append(str.toFloat()); + } + + for (int i=0;irowCount();i++) { + QString str = tblB->item(i,0)->text(); + if (str.isEmpty()) break; + b.append(str.toFloat()); + } +} diff --git a/transferfuncdialog.h b/transferfuncdialog.h index c141f7fd06..1614e25f5d 100644 --- a/transferfuncdialog.h +++ b/transferfuncdialog.h @@ -25,6 +25,8 @@ class TransferFuncDialog : public QDialog public: explicit TransferFuncDialog(QWidget *parent = 0); + + void getCoeffs(QVector &a, QVector &b); signals: From 188a4e5bbcaa2b33c36457f8f81a4a539fbc7c54 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 16 May 2014 14:00:58 +0400 Subject: [PATCH 69/90] getCoeffs() works --- filtersintez.cpp | 7 ++++++- transferfuncdialog.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 311fb4c9a5..de713e537b 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -371,8 +371,13 @@ void FilterSintez::slotSwitchParameters() void FilterSintez::slotDefineTransferFunc() { + QVector a,b; + TransferFuncDialog *trfuncdlg = new TransferFuncDialog(this); - trfuncdlg->exec(); + if (trfuncdlg->exec()) { + trfuncdlg->getCoeffs(a,b); + qDebug()< &a, QVector &b) a.clear(); b.clear(); - for (int i=0;irowCount();i++) { - QString str = tblA->item(i,0)->text(); - if (str.isEmpty()) break; - a.append(str.toFloat()); + for (int i=0;i< tblA->rowCount();i++) { + QTableWidgetItem *itm = tblA->item(i,0); + if (itm!=0) { + QString str = itm->text(); + if (str.isEmpty()) break; + bool ok; + float n = str.toFloat(&ok); + //qDebug()<rowCount();i++) { - QString str = tblB->item(i,0)->text(); - if (str.isEmpty()) break; - b.append(str.toFloat()); + + + for (int i=0;i< tblB->rowCount();i++) { + QTableWidgetItem *itm = tblB->item(i,0); + if (itm!=0) { + QString str = itm->text(); + if (str.isEmpty()) break; + bool ok; + float n = str.toFloat(&ok); + //qDebug()< Date: Fri, 16 May 2014 14:52:53 +0400 Subject: [PATCH 70/90] Added stubs for setting transfer function --- filter.cpp | 14 ++++++++++---- filter.h | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/filter.cpp b/filter.cpp index 633009fda2..e728d76c26 100644 --- a/filter.cpp +++ b/filter.cpp @@ -452,14 +452,20 @@ void Filter::calcUserTrFunc() qf_poly Numenator(2,a); - qf_poly Denomenetor(2,b); + qf_poly Denomenator(2,b); Numenator.to_roots(); - Denomenetor.to_roots(); + Denomenator.to_roots(); Numenator.disp_c(); - Denomenetor.disp_c(); + Denomenator.disp_c(); Numenator.roots_to_complex(Zeros); - Denomenetor.roots_to_complex(Poles); + Denomenator.roots_to_complex(Poles); +} + +void Filter::set_TrFunc(QVector a, QVector b) +{ + vec_A = a; + vec_B = b; } diff --git a/filter.h b/filter.h index f149f02a38..62228f77b8 100644 --- a/filter.h +++ b/filter.h @@ -39,6 +39,8 @@ class Filter protected: QVector< std::complex > Poles; QVector< std::complex > Zeros; + QVector vec_B; // Transfer function numenator + QVector vec_A; // and denominator QVector Sections; Filter::FType ftype; @@ -79,9 +81,10 @@ class Filter virtual void createSchematic(QString &s); - virtual bool calcFilter(); + void set_TrFunc(QVector a, QVector b); + }; #endif // FILTER_H From 8aeb793a1d0b120e633b7a852b91fb05d0aa3b90 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 17 May 2014 16:15:37 +0400 Subject: [PATCH 71/90] Transfer func coeffs converted to long double for qf_poly compatibility --- filtersintez.cpp | 4 ++-- filtersintez.h | 4 ++-- transferfuncdialog.cpp | 14 +++++++++++--- transferfuncdialog.h | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index de713e537b..dcc408eedc 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -371,12 +371,12 @@ void FilterSintez::slotSwitchParameters() void FilterSintez::slotDefineTransferFunc() { - QVector a,b; + QVector a,b; TransferFuncDialog *trfuncdlg = new TransferFuncDialog(this); if (trfuncdlg->exec()) { trfuncdlg->getCoeffs(a,b); - qDebug()< coeffB; - QVector coeffC; + QVector coeffB; + QVector coeffC; Filter::FType ftyp; diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index ed28682f96..32f4bb1a32 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -6,18 +6,26 @@ TransferFuncDialog::TransferFuncDialog(QWidget *parent) : lblB = new QLabel(tr("Numenator b[i]=")); lblA = new QLabel(tr("Denomenator a[i]=")); + QStringList indexes; + for (int i=0;i<50;i++) { + indexes<setColumnCount(head1.count()); tblA->setRowCount(50); tblA->setHorizontalHeaderLabels(head1); + tblA->setVerticalHeaderLabels(indexes); + tblB = new QTableWidget; QStringList head2; head2<setColumnCount(head2.count()); tblB->setRowCount(50); tblB->setHorizontalHeaderLabels(head2); + tblB->setVerticalHeaderLabels(indexes); btnAccept = new QPushButton(tr("Accept")); connect(btnAccept,SIGNAL(clicked()),this,SLOT(accept())); @@ -49,7 +57,7 @@ TransferFuncDialog::TransferFuncDialog(QWidget *parent) : } -void TransferFuncDialog::getCoeffs(QVector &a, QVector &b) +void TransferFuncDialog::getCoeffs(QVector &a, QVector &b) { a.clear(); b.clear(); @@ -60,7 +68,7 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector &b) QString str = itm->text(); if (str.isEmpty()) break; bool ok; - float n = str.toFloat(&ok); + long double n = (long double) str.toDouble(&ok); //qDebug()< &a, QVector &b) QString str = itm->text(); if (str.isEmpty()) break; bool ok; - float n = str.toFloat(&ok); + long double n = (long double) str.toDouble(&ok); //qDebug()< &a, QVector &b); + void getCoeffs(QVector &a, QVector &b); signals: From 40d7fa4cae49fde57b92046b3478fa69c6f7d602 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sat, 17 May 2014 16:24:27 +0400 Subject: [PATCH 72/90] Implemented transfer function coeffs saving --- filtersintez.cpp | 5 ++--- filtersintez.h | 2 +- transferfuncdialog.cpp | 25 ++++++++++++++++++++++++- transferfuncdialog.h | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index dcc408eedc..1dfdd93882 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -371,11 +371,10 @@ void FilterSintez::slotSwitchParameters() void FilterSintez::slotDefineTransferFunc() { - QVector a,b; - TransferFuncDialog *trfuncdlg = new TransferFuncDialog(this); + TransferFuncDialog *trfuncdlg = new TransferFuncDialog(coeffA,coeffB,this); if (trfuncdlg->exec()) { - trfuncdlg->getCoeffs(a,b); + trfuncdlg->getCoeffs(coeffA,coeffB); //qDebug()< coeffB; - QVector coeffC; + QVector coeffA; Filter::FType ftyp; diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index 32f4bb1a32..f773d6db27 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -1,6 +1,6 @@ #include "transferfuncdialog.h" -TransferFuncDialog::TransferFuncDialog(QWidget *parent) : +TransferFuncDialog::TransferFuncDialog(QVector &a, QVector &b, QWidget *parent) : QDialog(parent) { lblB = new QLabel(tr("Numenator b[i]=")); @@ -19,6 +19,18 @@ TransferFuncDialog::TransferFuncDialog(QWidget *parent) : tblA->setHorizontalHeaderLabels(head1); tblA->setVerticalHeaderLabels(indexes); + if (!a.isEmpty()) { + long double num; + int i = 0; + + foreach (num,a) { + QTableWidgetItem *it = new QTableWidgetItem(QString::number((double)num)); + tblA->setItem(i,0,it); + i++; + } + } + + tblB = new QTableWidget; QStringList head2; head2<setHorizontalHeaderLabels(head2); tblB->setVerticalHeaderLabels(indexes); + if (!b.isEmpty()) { + long double num; + int i = 0; + + foreach (num,b) { + QTableWidgetItem *it = new QTableWidgetItem(QString::number((double)num)); + tblB->setItem(i,0,it); + i++; + } + } + btnAccept = new QPushButton(tr("Accept")); connect(btnAccept,SIGNAL(clicked()),this,SLOT(accept())); btnCancel = new QPushButton(tr("Cancel")); diff --git a/transferfuncdialog.h b/transferfuncdialog.h index fcd956f0a2..03fc21838e 100644 --- a/transferfuncdialog.h +++ b/transferfuncdialog.h @@ -24,7 +24,7 @@ class TransferFuncDialog : public QDialog QHBoxLayout *low3; public: - explicit TransferFuncDialog(QWidget *parent = 0); + explicit TransferFuncDialog(QVector &a, QVector &b, QWidget *parent = 0); void getCoeffs(QVector &a, QVector &b); From 000b96dce661d1635b630ce47a41bb13bda935b9 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 18 May 2014 16:58:00 +0400 Subject: [PATCH 73/90] Implemented transfer function coeffs transferring to Filter class --- filter.cpp | 24 +++++++++++++----------- filter.h | 6 +++--- filtersintez.cpp | 6 ++++++ transferfuncdialog.cpp | 4 ++-- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/filter.cpp b/filter.cpp index e728d76c26..7e37f57556 100644 --- a/filter.cpp +++ b/filter.cpp @@ -447,24 +447,26 @@ void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 void Filter::calcUserTrFunc() { - long double a[3]={1,2,1}; - long double b[3]={2,2,1}; + if ((!vec_A.isEmpty())&&(!vec_B.isEmpty())) { + long double *a = vec_A.data(); + long double *b = vec_B.data(); + qf_poly Numenator(2,a); + qf_poly Denomenator(2,b); - qf_poly Numenator(2,a); - qf_poly Denomenator(2,b); + Numenator.to_roots(); + Denomenator.to_roots(); - Numenator.to_roots(); - Denomenator.to_roots(); + Numenator.disp_c(); + Denomenator.disp_c(); - Numenator.disp_c(); - Denomenator.disp_c(); + Numenator.roots_to_complex(Zeros); + Denomenator.roots_to_complex(Poles); + } - Numenator.roots_to_complex(Zeros); - Denomenator.roots_to_complex(Poles); } -void Filter::set_TrFunc(QVector a, QVector b) +void Filter::set_TrFunc(QVector a, QVector b) { vec_A = a; vec_B = b; diff --git a/filter.h b/filter.h index 62228f77b8..a50ef7f5f3 100644 --- a/filter.h +++ b/filter.h @@ -39,8 +39,8 @@ class Filter protected: QVector< std::complex > Poles; QVector< std::complex > Zeros; - QVector vec_B; // Transfer function numenator - QVector vec_A; // and denominator + QVector vec_B; // Transfer function numenator + QVector vec_A; // and denominator QVector Sections; Filter::FType ftype; @@ -83,7 +83,7 @@ class Filter virtual bool calcFilter(); - void set_TrFunc(QVector a, QVector b); + void set_TrFunc(QVector a, QVector b); }; diff --git a/filtersintez.cpp b/filtersintez.cpp index 1dfdd93882..b6fc3e7b9d 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -235,6 +235,9 @@ void FilterSintez::slotCalcSchematic() QString s; if (!((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) { MFBfilter mfb(ffunc,ftyp,par); + if (ffunc==Filter::User) { + mfb.set_TrFunc(coeffA,coeffB); + } bool ok = mfb.calcFilter(); mfb.createPolesZerosList(lst); mfb.createPartList(lst); @@ -254,6 +257,9 @@ void FilterSintez::slotCalcSchematic() case 2 : { QString s; SallenKey sk(ffunc,ftyp,par); + if (ffunc==Filter::User) { + sk.set_TrFunc(coeffA,coeffB); + } bool ok = sk.calcFilter(); sk.createPolesZerosList(lst); sk.createPartList(lst); diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index f773d6db27..6cc3f4d370 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -85,7 +85,7 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector a.clear(); b.clear(); - for (int i=0;i< tblA->rowCount();i++) { + for (int i=tblA->rowCount()-1;i>=0;i--) { QTableWidgetItem *itm = tblA->item(i,0); if (itm!=0) { QString str = itm->text(); @@ -99,7 +99,7 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector - for (int i=0;i< tblB->rowCount();i++) { + for (int i=tblB->rowCount()-1;i>=0;i--) { QTableWidgetItem *itm = tblB->item(i,0); if (itm!=0) { QString str = itm->text(); From 92bde93124b1ecaa30be591ce3b5956a80231cb4 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 19 May 2014 19:55:21 +0400 Subject: [PATCH 74/90] Implemented sparce A and B vectors input --- transferfuncdialog.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index 6cc3f4d370..eb7a3390c6 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -85,29 +85,36 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector a.clear(); b.clear(); + bool a0 = false; + for (int i=tblA->rowCount()-1;i>=0;i--) { QTableWidgetItem *itm = tblA->item(i,0); if (itm!=0) { + + if (!a0) a0 = true; + QString str = itm->text(); - if (str.isEmpty()) break; + //if ((str.isEmpty())&&(!a0)) break; bool ok; long double n = (long double) str.toDouble(&ok); - //qDebug()<rowCount()-1;i>=0;i--) { QTableWidgetItem *itm = tblB->item(i,0); if (itm!=0) { + + if (!b0) b0 = true; + QString str = itm->text(); - if (str.isEmpty()) break; + //if ((str.isEmpty())&&(!b0)) break; bool ok; long double n = (long double) str.toDouble(&ok); - //qDebug()< Date: Thu, 22 May 2014 13:43:40 +0400 Subject: [PATCH 75/90] Order determination for user defined transfer function fixed. Sparce transfer function polynomials functionality removed --- filter.cpp | 7 +++++-- filtersintez.cpp | 1 - transferfuncdialog.cpp | 26 ++++++++++++++------------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/filter.cpp b/filter.cpp index 7e37f57556..f455eab055 100644 --- a/filter.cpp +++ b/filter.cpp @@ -451,8 +451,11 @@ void Filter::calcUserTrFunc() long double *a = vec_A.data(); long double *b = vec_B.data(); - qf_poly Numenator(2,a); - qf_poly Denomenator(2,b); + int a_order = vec_A.count() - 1; + int b_order = vec_B.count() - 1; + + qf_poly Numenator(a_order,a); + qf_poly Denomenator(b_order,b); Numenator.to_roots(); Denomenator.to_roots(); diff --git a/filtersintez.cpp b/filtersintez.cpp index b6fc3e7b9d..6d0a909ad9 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -381,7 +381,6 @@ void FilterSintez::slotDefineTransferFunc() TransferFuncDialog *trfuncdlg = new TransferFuncDialog(coeffA,coeffB,this); if (trfuncdlg->exec()) { trfuncdlg->getCoeffs(coeffA,coeffB); - //qDebug()< &a, QVectorsetItem(i,0,it); - i++; + i--; } } @@ -41,12 +41,12 @@ TransferFuncDialog::TransferFuncDialog(QVector &a, QVectorsetItem(i,0,it); - i++; + i--; } } @@ -85,36 +85,38 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector a.clear(); b.clear(); - bool a0 = false; + // bool a0 = false; for (int i=tblA->rowCount()-1;i>=0;i--) { QTableWidgetItem *itm = tblA->item(i,0); if (itm!=0) { - if (!a0) a0 = true; + //if (!a0) a0 = true; QString str = itm->text(); - //if ((str.isEmpty())&&(!a0)) break; + if ((str.isEmpty())) break; bool ok; long double n = (long double) str.toDouble(&ok); if (ok) a.append(n); - } else if (a0) a.append(0.0); + } + //else if (a0) a.append(0.0); } - bool b0 = true; + //bool b0 = true; for (int i=tblB->rowCount()-1;i>=0;i--) { QTableWidgetItem *itm = tblB->item(i,0); if (itm!=0) { - if (!b0) b0 = true; + //if (!b0) b0 = true; QString str = itm->text(); - //if ((str.isEmpty())&&(!b0)) break; + if ((str.isEmpty())) break; bool ok; long double n = (long double) str.toDouble(&ok); if (ok) b.append(n); - } else if (b0) b.append(0.0); + } + //else if (b0) b.append(0.0); } } From 250612457c2761563aa9ead5ed3a0de68184f5e2 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 22 May 2014 13:57:17 +0400 Subject: [PATCH 76/90] Fixed user transfer function tables column width --- filter.cpp | 5 +++++ filter.h | 1 + transferfuncdialog.cpp | 2 ++ 3 files changed, 8 insertions(+) diff --git a/filter.cpp b/filter.cpp index f455eab055..ba6fece031 100644 --- a/filter.cpp +++ b/filter.cpp @@ -469,6 +469,11 @@ void Filter::calcUserTrFunc() } +void Filter::reformPolesZeros() +{ + +} + void Filter::set_TrFunc(QVector a, QVector b) { vec_A = a; diff --git a/filter.h b/filter.h index a50ef7f5f3..77c13c4f89 100644 --- a/filter.h +++ b/filter.h @@ -35,6 +35,7 @@ class Filter private: void besselCoefficients(); void cauerOrderEstim(); + void reformPolesZeros(); protected: QVector< std::complex > Poles; diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index 26e7f8bafc..185ab3a828 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -18,6 +18,7 @@ TransferFuncDialog::TransferFuncDialog(QVector &a, QVectorsetRowCount(50); tblA->setHorizontalHeaderLabels(head1); tblA->setVerticalHeaderLabels(indexes); + tblA->setFixedWidth(150); if (!a.isEmpty()) { long double num; @@ -38,6 +39,7 @@ TransferFuncDialog::TransferFuncDialog(QVector &a, QVectorsetRowCount(50); tblB->setHorizontalHeaderLabels(head2); tblB->setVerticalHeaderLabels(indexes); + tblB->setFixedWidth(150); if (!b.isEmpty()) { long double num; From bdf5f1cd851182e383974591fc072d0250abd3c6 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 25 May 2014 13:53:27 +0400 Subject: [PATCH 77/90] Fixed SVG images and removed russian labels in main window --- AFR.svg | 18 +- cauer.svg | 2195 +++++++++++++++++++++++++++++----------- filtersintez.cpp | 41 +- filtersintez.h | 3 + high-pass.svg | 16 +- mfb-highpass.svg | 1453 ++++++++++++++++++-------- mfb-lowpass.svg | 1453 ++++++++++++++++++-------- sk-highpass.svg | 1555 ++++++++++++++++++++-------- sk-lowpass.svg | 1555 ++++++++++++++++++++-------- transferfuncdialog.cpp | 6 + transferfuncdialog.h | 3 + 11 files changed, 5986 insertions(+), 2312 deletions(-) diff --git a/AFR.svg b/AFR.svg index efa4098f07..04a1f40d48 100644 --- a/AFR.svg +++ b/AFR.svg @@ -83,7 +83,7 @@ inkscape:pageshadow="2" inkscape:zoom="2.8" inkscape:cx="82.130173" - inkscape:cy="76.828431" + inkscape:cy="77.007002" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -117,7 +117,7 @@ image/svg+xml - + @@ -137,7 +137,7 @@ id="path3757" inkscape:connector-curvature="0" /> - АЧХ фильтра diff --git a/cauer.svg b/cauer.svg index acf9ceee3c..48308459c9 100644 --- a/cauer.svg +++ b/cauer.svg @@ -1,604 +1,1595 @@ - -Qt Svg Document -Generated with Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - -R1 - - - - - - - - - - - - - - - - - - - - - -OP3 - - - - - - - - - - - - - - - - - - - - - -OP2 - - - - - - - - - - - - - -C1 - - - - - - - - - - - - - - - - - - - - - -OP1 - - - - - - - - - - - - - - - - - - - - - - - -C2 - - - - - - - - - - - - -R5 - - - - - - - - - - - - -R4 - - - - - - - - - - - - -R2 - - - - - - - - - - - - -R3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -V1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -output - - - - - - - - - - - - - - - - - - - - -input - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + image/svg+xml + + + + + + Qt Svg Document + Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + R1 + + + + + + + + + + + + + + + + + + OP3 + + + + + + + + + + + + + + + + + + OP2 + + + + + + + + + + + C1 + + + + + + + + + + + + + + + + + + OP1 + + + + + + + + + + + + + + + + + + + C2 + + + + + + + + + + + R5 + + + + + + + + + + + R4 + + + + + + + + + + + R2 + + + + + + + + + + + R3 + + + + + + + + + + + + + + + + + + + + + + + + + + + V1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output + + + + + + + + + + + + + + + + + + input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/filtersintez.cpp b/filtersintez.cpp index 6d0a909ad9..df66444d8f 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -16,13 +16,13 @@ FilterSintez::FilterSintez(QWidget *parent) QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); //lblInputData = new QLabel(tr("Входные данные")); - lblA1 = new QLabel(tr("Затухание в полосе пропускания, Ap")); - lblA2 = new QLabel(tr("Мин. затухание в полосе задерживания, As")); - lblF1 = new QLabel(tr("Частота среза фильтра, Fc (Гц)")); - lblF2 = new QLabel(tr("Начало полосы задерживания, Fs (Гц)")); - lblRpl1 = new QLabel(tr("Амплитуда пульсаций в полосе пропускания Rp(дБ)")); - //lblRpl2 = new QLabel(tr("Амплитуда пульсаций в полосе задерживания (дБ)")); - lblKv = new QLabel(tr("Усиление фильтра, Kv (дБ)")); + lblA1 = new QLabel(tr("Passband attenuation, Ap")); + lblA2 = new QLabel(tr("Stopband attenuation, As")); + lblF1 = new QLabel(tr("Cuttof frequency, Fc (Гц)")); + lblF2 = new QLabel(tr("Stopband frequency, Fs (Гц)")); + lblRpl1 = new QLabel(tr("Passband ripple Rp(дБ)")); + //lblRpl2 = new QLabel(tr("Stopband ripple (дБ)")); + lblKv = new QLabel(tr("Passband gain, Kv (дБ)")); edtA1 = new QLineEdit("3"); @@ -41,13 +41,13 @@ FilterSintez::FilterSintez(QWidget *parent) edtKv = new QLineEdit("0"); edtKv->setValidator(val1); - lblTyp = new QLabel(tr("Рассчитать фильтр:")); + lblTyp = new QLabel(tr("Approximation type:")); cbxFilterFunc = new QComboBox; QStringList lst2; - lst2<addItems(lst2); connect(cbxFilterFunc,SIGNAL(currentIndexChanged(int)),this,SLOT(slotSwitchParameters())); @@ -56,14 +56,14 @@ FilterSintez::FilterSintez(QWidget *parent) btnDefineTransferFunc->setEnabled(false); connect(btnDefineTransferFunc,SIGNAL(clicked()),this,SLOT(slotDefineTransferFunc())); - btnCalcSchematic = new QPushButton(tr("Рассчитать элементы схемы фильтра")); + btnCalcSchematic = new QPushButton(tr("Calculate and copy to clipboard")); connect(btnCalcSchematic,SIGNAL(clicked()),SLOT(slotCalcSchematic())); - lblResult = new QLabel(tr("Результаты расчёта: ")); + lblResult = new QLabel(tr("Calculation console")); txtResult = new QTextEdit; - lblSch = new QLabel(tr("Схемная реализация фильтра")); + lblSch = new QLabel(tr("Filter topology")); lblResp = new QLabel(tr("Filter type:")); cbxResponse = new QComboBox; QStringList lst3; @@ -78,13 +78,16 @@ FilterSintez::FilterSintez(QWidget *parent) cbxFilterType = new QComboBox; QStringList lst; lst<addItems(lst); connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic())); this->slotSwitchParameters(); + lblAFR = new QLabel(tr("General amplitude frequenc response")); + lblTopology = new QLabel(tr("Filter topology preview (one stage)")); + QString s1 = ":/images/AFR.svg"; QSvgRenderer *ren = new QSvgRenderer(s1); QSize sz = ren->defaultSize(); @@ -140,7 +143,9 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(btnCalcSchematic); left->addStretch(); + right->addWidget(lblAFR); right->addWidget(imgAFR); + right->addWidget(lblTopology); right->addWidget(sch_pic); right->addStretch(); diff --git a/filtersintez.h b/filtersintez.h index 1634e11ae0..b152971032 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -23,6 +23,9 @@ class FilterSintez : public QMainWindow QLabel *lblRpl2; QLabel *lblResp; + QLabel *lblAFR; + QLabel *lblTopology; + QLineEdit *edtA1; // passband attenuation A1 QLineEdit *edtA2; // stopband attenuation A2 QLineEdit *edtF1; // passband cutoff frequency F1 diff --git a/high-pass.svg b/high-pass.svg index 8310c97922..342637b272 100644 --- a/high-pass.svg +++ b/high-pass.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.48.3.1 r9886" - sodipodi:docname="AFR.svg"> + sodipodi:docname="high-pass.svg"> image/svg+xml - + @@ -383,18 +383,6 @@ d="m 177.16535,102.75588 -3.5433,10.62992 -3.54331,-10.62992" id="path8659" inkscape:connector-curvature="0" /> - АЧХ фильтра - -Qt Svg Document -Generated with Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OP1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -V1 - - - - - - - - - - - - -R2 - - - - - - - - - - - - -R1 - - - - - - - - - - - - - -C3 - - - - - - - - - - - - - -C2 - - - - - - - - - - - - - -C1 - - - - - - - - - - - - - - - - - -output - - - - - - - - - - - - - - - - -input - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + image/svg+xml + + + + + + Qt Svg Document + Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OP1 + + + + + + + + + + + + + + + + + + + + + + + + + + + V1 + + + + + + + + + + + R2 + + + + + + + + + + + R1 + + + + + + + + + + + C3 + + + + + + + + + + + C2 + + + + + + + + + + + C1 + + + + + + + + + + + + + + + + output + + + + + + + + + + + + + + input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mfb-lowpass.svg b/mfb-lowpass.svg index e96314ac8d..9f67fa0b1b 100644 --- a/mfb-lowpass.svg +++ b/mfb-lowpass.svg @@ -1,404 +1,1053 @@ - -Qt Svg Document -Generated with Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -R3 - - - - - - - - - - - - -R2 - - - - - - - - - - - - -R1 - - - - - - - - - - - - - -C2 - - - - - - - - - - - - - - - - - - - - - -OP1 - - - - - - - - - - - - - -C1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -V1 - - - - - - - - - - - - - - - - - - - -output - - - - - - - - - - - - - - - - -input - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + image/svg+xml + + + + + + Qt Svg Document + Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + R3 + + + + + + + + + + + R2 + + + + + + + + + + + R1 + + + + + + + + + + + C2 + + + + + + + + + + + + + + + + + + OP1 + + + + + + + + + + + C1 + + + + + + + + + + + + + + + + + + + + + + + + + + + V1 + + + + + + + + + + + + + + + + + + output + + + + + + + + + + + + + + input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sk-highpass.svg b/sk-highpass.svg index f3de1a6b4a..0b52a24109 100644 --- a/sk-highpass.svg +++ b/sk-highpass.svg @@ -1,430 +1,1129 @@ - -Qt Svg Document -Generated with Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -C1 - - - - - - - - - - - - - -C2 - - - - - - - - - - - - -R1 - - - - - - - - - - - - -R2 - - - - - - - - - - - - -R4 - - - - - - - - - - - - -R3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -V1 - - - - - - - - - - - - - - - - - - - - - -OP1 - - - - - - - - -output - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -input - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + image/svg+xml + + + + + + Qt Svg Document + Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + C1 + + + + + + + + + + + C2 + + + + + + + + + + + R1 + + + + + + + + + + + R2 + + + + + + + + + + + R4 + + + + + + + + + + + R3 + + + + + + + + + + + + + + + + + + + + + + + + + + + V1 + + + + + + + + + + + + + + + + + + OP1 + + + + + + + output + + + + + + + + + + + + + + + + + + + + + + + + + + + input + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sk-lowpass.svg b/sk-lowpass.svg index 4c8e3812fa..c9ae3d2194 100644 --- a/sk-lowpass.svg +++ b/sk-lowpass.svg @@ -1,430 +1,1129 @@ - -Qt Svg Document -Generated with Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -R4 - - - - - - - - - - - - -R3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -V1 - - - - - - - - - - - - - - - - - - - - - -OP1 - - - - - - - - - - - - -R1 - - - - - - - - - - - - -R2 - - - - - - - - - - - - - -C2 - - - - - - - - - - - - - -C1 - - - - - - - - - - - - - - - - - - -input - - - - - - - - - - - - - - - - - - - -output - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + image/svg+xml + + + + + + Qt Svg Document + Generated with Qt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + R4 + + + + + + + + + + + R3 + + + + + + + + + + + + + + + + + + + + + + + + + + + V1 + + + + + + + + + + + + + + + + + + OP1 + + + + + + + + + + + R1 + + + + + + + + + + + R2 + + + + + + + + + + + C2 + + + + + + + + + + + C1 + + + + + + + + + + + + + + + + + input + + + + + + + + + + + + + + + + + output + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index 185ab3a828..cb8419f151 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -54,6 +54,7 @@ TransferFuncDialog::TransferFuncDialog(QVector &a, QVector &a, QVector //else if (b0) b.append(0.0); } } + +void TransferFuncDialog::slotCheckCoeffs() +{ + +} diff --git a/transferfuncdialog.h b/transferfuncdialog.h index 03fc21838e..b023ccf600 100644 --- a/transferfuncdialog.h +++ b/transferfuncdialog.h @@ -30,6 +30,9 @@ class TransferFuncDialog : public QDialog signals: +private slots: + void slotCheckCoeffs(); + public slots: }; From 2400f44cc8bf2fa149cbd4c2712b6339040cced2 Mon Sep 17 00:00:00 2001 From: Vadim Kusnetzov Date: Wed, 28 May 2014 10:31:45 +0400 Subject: [PATCH 78/90] Added copy to cpipboard function --- filter.cpp | 4 ++-- filtersintez.cpp | 33 +++++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/filter.cpp b/filter.cpp index ba6fece031..bea1a1c4d3 100644 --- a/filter.cpp +++ b/filter.cpp @@ -28,11 +28,11 @@ void Filter::createSchematic(QString &s) default: break; } - QFile sch("filter.sch"); + /*QFile sch("filter.sch"); sch.open(QFile::WriteOnly); QTextStream out(&sch); out<slotSwitchParameters(); - lblAFR = new QLabel(tr("General amplitude frequenc response")); + lblAFR = new QLabel(tr("General amplitude frequency response")); lblTopology = new QLabel(tr("Filter topology preview (one stage)")); QString s1 = ":/images/AFR.svg"; @@ -217,18 +217,23 @@ void FilterSintez::slotCalcSchematic() break; } + QString s; + bool ok = false; + switch (cbxFilterType->currentIndex()) { - case 0 : { - QString s; + case 0 : { if (((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) { SchCauer cauer(ffunc,ftyp,par); - bool ok = cauer.calcFilter(); + ok = cauer.calcFilter(); cauer.createPolesZerosList(lst); cauer.createPartList(lst); + txtResult->setText(lst.join("\n")); if (ok) { cauer.createSchematic(s); + } else { + errorMessage(tr("Unable to implement filter with such parameters and topology \n" + "Change parapeters and/or topology and try again!")); } - txtResult->setText(lst.join("\n")); } else { errorMessage(tr("Unable to use Cauer section for Chebyshev or Butterworth \n" "frequency response. Try to use another topology.")); @@ -236,14 +241,13 @@ void FilterSintez::slotCalcSchematic() } break; - case 1 : { - QString s; + case 1 : { if (!((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) { MFBfilter mfb(ffunc,ftyp,par); if (ffunc==Filter::User) { mfb.set_TrFunc(coeffA,coeffB); } - bool ok = mfb.calcFilter(); + ok = mfb.calcFilter(); mfb.createPolesZerosList(lst); mfb.createPartList(lst); txtResult->setText(lst.join("\n")); @@ -260,12 +264,11 @@ void FilterSintez::slotCalcSchematic() } break; case 2 : { - QString s; SallenKey sk(ffunc,ftyp,par); if (ffunc==Filter::User) { sk.set_TrFunc(coeffA,coeffB); } - bool ok = sk.calcFilter(); + ok = sk.calcFilter(); sk.createPolesZerosList(lst); sk.createPartList(lst); txtResult->setText(lst.join("\n")); @@ -281,6 +284,16 @@ void FilterSintez::slotCalcSchematic() break; default: break; } + + if (ok) { + txtResult->append(tr("\nFilter calculation was sucessfull")); + } else { + txtResult->append(tr("\nFilter calculation terminated with error")); + } + + QClipboard *cb = QApplication::clipboard(); + cb->setText(s); + } void FilterSintez::slotUpdateResponse() From 7eaf7bdc7f06697e5dcc6639bcf38f81bb2b1a80 Mon Sep 17 00:00:00 2001 From: Vadim Kusnetzov Date: Wed, 28 May 2014 14:25:29 +0400 Subject: [PATCH 79/90] Tested filter sintez by user def. transfer function. Works with errors. --- filter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/filter.cpp b/filter.cpp index bea1a1c4d3..23cc5befec 100644 --- a/filter.cpp +++ b/filter.cpp @@ -61,7 +61,9 @@ bool Filter::calcFilter() case Filter::InvChebyshev : calcInvChebyshev(); break; case Filter::User : calcUserTrFunc(); - default : return false; + break; + default : + return false; break; } @@ -454,6 +456,8 @@ void Filter::calcUserTrFunc() int a_order = vec_A.count() - 1; int b_order = vec_B.count() - 1; + order = std::max(a_order,b_order); + qf_poly Numenator(a_order,a); qf_poly Denomenator(b_order,b); From b93e993597a2b76108ca058cdc65a730346429f5 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 29 May 2014 13:24:39 +0400 Subject: [PATCH 80/90] Fixed crashing at aemty string in userdef tr.func. coeffs list and at emty tr.func coeffs list --- filter.cpp | 10 ++++++++++ transferfuncdialog.cpp | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/filter.cpp b/filter.cpp index 23cc5befec..9daf3979b8 100644 --- a/filter.cpp +++ b/filter.cpp @@ -67,6 +67,16 @@ bool Filter::calcFilter() break; } + if (Poles.isEmpty()) { + return false; + } + + if (((ffunc==Filter::Cauer)|| + (ffunc==Filter::InvChebyshev)) + &&(Zeros.isEmpty())) { + return false; + } + switch (ftype) { case Filter::LowPass : calcLowPass(); break; diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index cb8419f151..5d06162b00 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -97,7 +97,7 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector //if (!a0) a0 = true; QString str = itm->text(); - if ((str.isEmpty())) break; + //if ((str.isEmpty())) break; bool ok; long double n = (long double) str.toDouble(&ok); if (ok) a.append(n); @@ -115,7 +115,7 @@ void TransferFuncDialog::getCoeffs(QVector &a, QVector //if (!b0) b0 = true; QString str = itm->text(); - if ((str.isEmpty())) break; + //if ((str.isEmpty())) break; bool ok; long double n = (long double) str.toDouble(&ok); if (ok) b.append(n); From 75e0d96b008534db0d7273458403fe07f3c6c93b Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 29 May 2014 13:41:44 +0400 Subject: [PATCH 81/90] Added poles and zeros list forming for user def.tr.func filters --- filter.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/filter.cpp b/filter.cpp index 9daf3979b8..5bf50cc17d 100644 --- a/filter.cpp +++ b/filter.cpp @@ -479,13 +479,34 @@ void Filter::calcUserTrFunc() Numenator.roots_to_complex(Zeros); Denomenator.roots_to_complex(Poles); + + reformPolesZeros(); } } void Filter::reformPolesZeros() { + int Np = Poles.count(); + int Nz = Zeros.count(); + + for (int i=0;i tmp; + tmp = Poles[i]; + Poles[i]=Poles[Np-1-i]; + Poles[Np-1-i]=tmp; + } + } + for (int i=0;i tmp; + tmp = Poles[i]; + Poles[i]=Poles[Nz-1-i]; + Poles[Nz-1-i]=tmp; + } + } } void Filter::set_TrFunc(QVector a, QVector b) From 93f6e905f6140c4d5d1ddde1e4ad3424d9f85a9c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Fri, 30 May 2014 19:26:46 +0400 Subject: [PATCH 82/90] Fixed numenator and denominator in user.def. tr.func --- filter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/filter.cpp b/filter.cpp index 5bf50cc17d..812a3830b7 100644 --- a/filter.cpp +++ b/filter.cpp @@ -468,8 +468,8 @@ void Filter::calcUserTrFunc() order = std::max(a_order,b_order); - qf_poly Numenator(a_order,a); - qf_poly Denomenator(b_order,b); + qf_poly Numenator(b_order,b); + qf_poly Denomenator(a_order,a); Numenator.to_roots(); Denomenator.to_roots(); From 90c8c101bd3b8bb60f68b6714c916f9a215947cc Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 6 Jul 2014 16:53:30 +0400 Subject: [PATCH 83/90] Added transfer function equition to manual transfer functiom definition dialog --- qfiltersintez.qrc | 1 + transferfuncdialog.cpp | 9 +++++++++ transferfuncdialog.h | 1 + trfunc.png | Bin 0 -> 7436 bytes 4 files changed, 11 insertions(+) create mode 100644 trfunc.png diff --git a/qfiltersintez.qrc b/qfiltersintez.qrc index d30e6821c5..8d3ecb2ab4 100644 --- a/qfiltersintez.qrc +++ b/qfiltersintez.qrc @@ -7,5 +7,6 @@ AFR.svg cauer.svg high-pass.svg + trfunc.png diff --git a/transferfuncdialog.cpp b/transferfuncdialog.cpp index 5d06162b00..056a6d20cd 100644 --- a/transferfuncdialog.cpp +++ b/transferfuncdialog.cpp @@ -3,6 +3,14 @@ TransferFuncDialog::TransferFuncDialog(QVector &a, QVector &b, QWidget *parent) : QDialog(parent) { + this->setWindowTitle(tr("Define filter transfer function")); + + imgTrfuncEq = new QLabel; + imgTrfuncEq->setPixmap(QPixmap(":images/trfunc.png")); + //imgTrfuncEq->setScaledContents(true); + + + lblB = new QLabel(tr("Numenator b[i]=")); lblA = new QLabel(tr("Denomenator a[i]=")); @@ -75,6 +83,7 @@ TransferFuncDialog::TransferFuncDialog(QVector &a, QVectoraddLayout(low2); top1 = new QVBoxLayout; + top1->addWidget(imgTrfuncEq); top1->addLayout(top); top1->addLayout(low3); diff --git a/transferfuncdialog.h b/transferfuncdialog.h index b023ccf600..f91a8fa869 100644 --- a/transferfuncdialog.h +++ b/transferfuncdialog.h @@ -11,6 +11,7 @@ class TransferFuncDialog : public QDialog private: QLabel *lblA; QLabel *lblB; + QLabel *imgTrfuncEq; QTableWidget *tblA; QTableWidget *tblB; diff --git a/trfunc.png b/trfunc.png new file mode 100644 index 0000000000000000000000000000000000000000..2ecbb4e143fd2b59f6c2bc5c8c923c5cf39037e9 GIT binary patch literal 7436 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 X)r9C2?k(_nCgPEdigdB0vG0EYsC7e` literal 0 HcmV?d00001 From 8f621347b4041aa10a6093c3ff48979aeed3a72c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Sun, 6 Jul 2014 17:31:38 +0400 Subject: [PATCH 84/90] Added Octave script to precalculate Bessel filter poles up to 20th order --- bessel-poles.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 bessel-poles.m diff --git a/bessel-poles.m b/bessel-poles.m new file mode 100755 index 0000000000..1380f2a014 --- /dev/null +++ b/bessel-poles.m @@ -0,0 +1,14 @@ +#!/usr/bin/octave -qf + +for n=1:20; + +b=1; +for k=1:n+1; +b(k)=factorial(2*n-(k-1))/((2^(n-(k-1)))*factorial(k-1)*factorial(n-(k-1))); +endfor; +b=fliplr(b); +#disp(b); +printf("Bessel polynomial %dth order poles:",n); +roots(b) + +endfor; From da79d3b34d678aba50471661143bd70207a578f7 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Mon, 7 Jul 2014 11:02:25 +0400 Subject: [PATCH 85/90] Autogenerated bessel.h --- Bessel filter poles table --- QFilterSintez.pro | 3 +- bessel-poles.m | 49 +++++++++++++++++++++++++++++-- bessel.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++ filter.cpp | 1 + 4 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 bessel.h diff --git a/QFilterSintez.pro b/QFilterSintez.pro index 2c07edafa5..d8533cbadc 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -28,7 +28,8 @@ HEADERS += filtersintez.h \ qf_poly.h \ qf_matrix.h \ schcauer.h \ - transferfuncdialog.h + transferfuncdialog.h \ + bessel.h RESOURCES += \ qfiltersintez.qrc diff --git a/bessel-poles.m b/bessel-poles.m index 1380f2a014..b8b13654d0 100755 --- a/bessel-poles.m +++ b/bessel-poles.m @@ -1,14 +1,57 @@ #!/usr/bin/octave -qf -for n=1:20; +printf("Generating bessel.h...\n"); +maxorder=20; + +fid=fopen("bessel.h","w"); +fprintf(fid,"#ifndef BESSEL_H\n"); +fprintf(fid,"#define BESSEL_H\n"); +fprintf(fid,"//Bessel coeffs table\n //Generated automatically! DO NOT EDIT!!!\n\n\n"); +fprintf(fid,"\n\ndouble BesselPoles[%d][%d]={\n\n",maxorder,2*maxorder); + +for n=1:maxorder; + +fprintf(fid,"/* %d th order */ {\n",n); b=1; for k=1:n+1; b(k)=factorial(2*n-(k-1))/((2^(n-(k-1)))*factorial(k-1)*factorial(n-(k-1))); endfor; b=fliplr(b); #disp(b); -printf("Bessel polynomial %dth order poles:",n); -roots(b) +#printf("Bessel polynomial %dth order poles:",n); +poles=roots(b); +Np=length(poles); + +for i=1:Np; +fprintf(fid," %f, ",real(poles(i))); +#fprintf(fid,"\t%f,\n",imag(poles(i))); +if (i==maxorder) +fprintf(fid," %f \n",imag(poles(i))); +else +fprintf(fid," %f, ",imag(poles(i))); +endif; +endfor; +for i=Np+1:maxorder; +#fprintf(fid," 0.0,\n"); +if (i==maxorder) +fprintf(fid," 0.0 \n"); +else +fprintf(fid," 0.0, "); +endif; endfor; + +if (n==maxorder) +fprintf(fid,"\t}\n"); +else +fprintf(fid,"\t},\n"); +endif; + +endfor; + +fprintf(fid,"\n};\n"); +fprintf(fid,"#endif\n"); +fclose(fid); + +printf("bessel.h successfully generated!\n"); diff --git a/bessel.h b/bessel.h new file mode 100644 index 0000000000..387d342b44 --- /dev/null +++ b/bessel.h @@ -0,0 +1,73 @@ +#ifndef BESSEL_H +#define BESSEL_H +//Bessel coeffs table + //Generated automatically! DO NOT EDIT!!! + + + + +double BesselPoles[20][40]={ + +/* 1 th order */ { + -1.000000, 0.000000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 2 th order */ { + -1.500000, 0.866025, -1.500000, -0.866025, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 3 th order */ { + -1.838907, 1.754381, -1.838907, -1.754381, -2.322185, 0.000000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 4 th order */ { + -2.103789, 2.657418, -2.103789, -2.657418, -2.896211, 0.867234, -2.896211, -0.867234, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 5 th order */ { + -2.324674, 3.571023, -2.324674, -3.571023, -3.646739, 0.000000, -3.351956, 1.742661, -3.351956, -1.742661, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 6 th order */ { + -2.515932, 4.492673, -2.515932, -4.492673, -3.735708, 2.626272, -3.735708, -2.626272, -4.248359, 0.867510, -4.248359, -0.867510, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 7 th order */ { + -2.685677, 5.420694, -2.685677, -5.420694, -4.070139, 3.517174, -4.070139, -3.517174, -4.971787, 0.000000, -4.758291, 1.739286, -4.758291, -1.739286, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 8 th order */ { + -2.838984, 6.353911, -2.838984, -6.353911, -4.368289, 4.414443, -4.368289, -4.414443, -5.204841, 2.616175, -5.204841, -2.616175, -5.587886, 0.867614, -5.587886, -0.867614, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 9 th order */ { + -2.979261, 7.291464, -2.979261, -7.291464, -4.638440, 5.317272, -4.638440, -5.317272, -5.604422, 3.498157, -5.604422, -3.498157, -6.297019, 0.000000, -6.129368, 1.737848, -6.129368, -1.737848, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 10 th order */ { + -3.108916, 8.232699, -3.108916, -8.232699, -4.886220, 6.224985, -4.886220, -6.224985, -5.967528, 4.384947, -5.967528, -4.384947, -6.615291, 2.611568, -6.615291, -2.611568, -6.922045, 0.867665, -6.922045, -0.867665, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 11 th order */ { + -3.229722, 9.177112, -3.229722, -9.177112, -5.115648, 7.137021, -5.115648, -7.137021, -6.301337, 5.276192, -6.301337, -5.276192, -7.057892, 3.489015, -7.057892, -3.489015, -7.622340, 0.000000, -7.484230, 1.737103, -7.484230, -1.737103, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 12 th order */ { + -3.343023, 10.124297, -3.343023, -10.124297, -5.329709, 8.052907, -5.329709, -8.052907, -6.611004, 6.171535, -6.611004, -6.171535, -7.465571, 4.370170, -7.465571, -4.370170, -7.997271, 2.609067, -7.997271, -2.609067, -8.253422, 0.867694, -8.253422, -0.867694, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 13 th order */ { + -3.449867, 11.073929, -3.449867, -11.073929, -5.530681, 8.972248, -5.530681, -8.972248, -6.900373, 7.070644, -6.900373, -7.070644, -7.844380, 5.254903, -7.844380, -5.254903, -8.470592, 3.483868, -8.470592, -3.483868, -8.947710, 0.000000, -8.830252, 1.736666, -8.830252, -1.736666, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 14 th order */ { + -3.551087, 12.025738, -3.551087, -12.025738, -5.720352, 9.894708, -5.720352, -9.894708, -7.172396, 7.973217, -7.172396, -7.973217, -8.198847, 6.143041, -8.198847, -6.143041, -8.911001, 4.361604, -8.911001, -4.361604, -9.363146, 2.607553, -9.363146, -2.607553, -9.583171, 0.867711, -9.583171, -0.867711, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 15 th order */ { + -3.647357, 12.979501, -3.647357, -12.979501, -5.900152, 10.819999, -5.900152, -10.819999, -7.429397, 8.878983, -7.429397, -8.878983, -8.532459, 7.034394, -8.532459, -7.034394, -9.323599, 5.242259, -9.323599, -5.242259, -9.859567, 3.480671, -9.859567, -3.480671, -10.273109, 0.000000, -10.170914, 1.736389, -10.170914, -1.736389, 0.0, 0.0, 0.0, 0.0, 0.0 + }, +/* 16 th order */ { + -3.739232, 13.935028, -3.739232, -13.935028, -6.071241, 11.747875, -6.071241, -11.747875, -7.673241, 9.787697, -7.673241, -9.787697, -8.847968, 7.928773, -8.847968, -7.928773, -9.712326, 6.125761, -9.712326, -6.125761, -10.325121, 4.356163, -10.325121, -4.356163, -10.911887, 0.867721, -10.911887, -0.867721, -10.718985, 2.606568, -10.718985, -2.606568, 0.0, 0.0, 0.0, 0.0 + }, +/* 17 th order */ { + -3.827174, 14.892159, -3.827174, -14.892159, -6.234581, 12.678120, -6.234581, -12.678120, -7.905450, 10.699145, -7.905450, -10.699145, -9.147588, 8.825998, -9.147588, -8.825998, -10.080296, 7.012010, -10.080296, -7.012010, -10.764132, 5.234075, -10.764132, -5.234075, -11.233439, 3.478542, -11.233439, -3.478542, -11.598530, 0.000000, -11.508076, 1.736203, -11.508076, -1.736203, 0.0, 0.0, 0.0 + }, +/* 18 th order */ { + -3.911572, 15.850754, -3.911572, -15.850754, -6.390973, 13.610547, -6.390973, -13.610547, -8.127284, 11.613132, -8.127284, -11.613132, -9.433133, 9.725901, -9.433133, -9.725901, -10.430010, 7.900893, -10.430010, -7.900893, -11.180044, 6.114391, -11.180044, -6.114391, -11.718943, 4.352488, -11.718943, -4.352488, -12.068139, 2.605877, -12.068139, -2.605877, -12.239902, 0.867741, -12.239902, -0.867741, 0.0, 0.0 + }, +/* 19 th order */ { + -3.992759, 16.810692, -3.992759, -16.810692, -6.541095, 14.544991, -6.541095, -14.544991, -8.339801, 12.529484, -8.339801, -12.529484, -9.706101, 10.628321, -9.706101, -10.628321, -10.763544, 8.792290, -10.763544, -8.792290, -11.575589, 6.997092, -11.575589, -6.997092, -12.179243, 5.228415, -12.179243, -5.228415, -12.597062, 3.477100, -12.597062, -3.477100, -12.923980, 0.000000, -12.842816, 1.736037, -12.842816, -1.736037, 0.0 + }, +/* 20 th order */ { + -4.071019, 17.771869, -4.071019, -17.771869, -6.685527, 15.481306, -6.685527, -15.481306, -8.543895, 13.448046, -8.543895, -13.448046, -9.967765, 11.533112, -9.967765, -11.533112, -11.082571, 9.686112, -11.082571, -9.686112, -11.953103, 7.881991, -11.953103, -7.881991, -12.617294, 6.106632, -12.617294, -6.106632, -13.098755, 4.349634, -13.098755, -4.349634, -13.567377, 0.867486, -13.567377, -0.867486, -13.412693, 2.605660, -13.412693, -2.605660 + } + +}; +#endif diff --git a/filter.cpp b/filter.cpp index 812a3830b7..035272bda0 100644 --- a/filter.cpp +++ b/filter.cpp @@ -1,5 +1,6 @@ #include "filter.h" #include "qf_poly.h" +#include "bessel.h" Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) { From 762b145987c169b43e031681cc5d5c1f805fb0bb Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Tue, 8 Jul 2014 16:29:12 +0400 Subject: [PATCH 86/90] Added controls to implement Bessel filter design --- filter.cpp | 7 +++++++ filtersintez.cpp | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/filter.cpp b/filter.cpp index 035272bda0..fa4d59bf34 100644 --- a/filter.cpp +++ b/filter.cpp @@ -61,6 +61,8 @@ bool Filter::calcFilter() break; case Filter::InvChebyshev : calcInvChebyshev(); break; + case Filter::Bessel : calcBessel(); + break; case Filter::User : calcUserTrFunc(); break; default : @@ -458,6 +460,11 @@ void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 } } +void Filter::calcBessel() +{ + +} + void Filter::calcUserTrFunc() { if ((!vec_A.isEmpty())&&(!vec_B.isEmpty())) { diff --git a/filtersintez.cpp b/filtersintez.cpp index 73093cbd05..c86c72d2b2 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -48,6 +48,7 @@ FilterSintez::FilterSintez(QWidget *parent) <addItems(lst2); connect(cbxFilterFunc,SIGNAL(currentIndexChanged(int)),this,SLOT(slotSwitchParameters())); @@ -196,7 +197,9 @@ void FilterSintez::slotCalcSchematic() break; case 3 : ffunc = Filter::Cauer; break; - case 4 : ffunc = Filter::User; + case 4 : ffunc = Filter::Bessel; + break; + case 5 : ffunc = Filter::User; break; default: ffunc = Filter::NoFunc; break; @@ -376,7 +379,7 @@ void FilterSintez::slotSwitchParameters() cbxFilterType->setDisabled(false); } - if ((cbxFilterFunc->currentIndex()==4)) { + if ((cbxFilterFunc->currentIndex()==5)) { btnDefineTransferFunc->setEnabled(true); edtF2->setEnabled(false); edtPassbRpl->setEnabled(false); From 7fd3c4dc6d7d77a96023d9765f9fb030dfa3c63c Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 9 Jul 2014 11:00:36 +0400 Subject: [PATCH 87/90] Added interface controls for filter order definition (for Bessel filter) --- filter.cpp | 3 +++ filter.h | 1 + filtersintez.cpp | 7 +++++++ filtersintez.h | 2 ++ 4 files changed, 13 insertions(+) diff --git a/filter.cpp b/filter.cpp index fa4d59bf34..df67a4c322 100644 --- a/filter.cpp +++ b/filter.cpp @@ -12,6 +12,9 @@ Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) As = par.As; Ap = par.Ap; Kv = par.Kv; + if (ffunc==Filter::Bessel) { + order = par.order; + } } Filter::~Filter() diff --git a/filter.h b/filter.h index 77c13c4f89..efc444fb37 100644 --- a/filter.h +++ b/filter.h @@ -23,6 +23,7 @@ struct FilterParam { float Fs; float Rp; float Kv; + int order; }; class Filter diff --git a/filtersintez.cpp b/filtersintez.cpp index c86c72d2b2..12ceef250a 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -40,6 +40,10 @@ FilterSintez::FilterSintez(QWidget *parent) //edtStopbRpl->setValidator(val1); edtKv = new QLineEdit("0"); edtKv->setValidator(val1); + QIntValidator *val2 = new QIntValidator(2,20); + lblOrder = new QLabel(tr("Filter order")); + edtOrder = new QLineEdit("5"); + edtOrder->setValidator(val2); lblTyp = new QLabel(tr("Approximation type:")); cbxFilterFunc = new QComboBox; @@ -126,6 +130,8 @@ FilterSintez::FilterSintez(QWidget *parent) left->addWidget(edtPassbRpl); left->addWidget(lblKv); left->addWidget(edtKv); + left->addWidget(lblOrder); + left->addWidget(edtOrder); QHBoxLayout *l3 = new QHBoxLayout; l3->addWidget(lblTyp); l3->addWidget(cbxFilterFunc); @@ -198,6 +204,7 @@ void FilterSintez::slotCalcSchematic() case 3 : ffunc = Filter::Cauer; break; case 4 : ffunc = Filter::Bessel; + par.order = edtOrder->text().toInt(); break; case 5 : ffunc = Filter::User; break; diff --git a/filtersintez.h b/filtersintez.h index b152971032..2ef7097fe4 100644 --- a/filtersintez.h +++ b/filtersintez.h @@ -25,6 +25,7 @@ class FilterSintez : public QMainWindow QLabel *lblAFR; QLabel *lblTopology; + QLabel *lblOrder; QLineEdit *edtA1; // passband attenuation A1 QLineEdit *edtA2; // stopband attenuation A2 @@ -33,6 +34,7 @@ class FilterSintez : public QMainWindow QLineEdit *edtKv; QLineEdit *edtPassbRpl; QLineEdit *edtStopbRpl; + QLineEdit *edtOrder; QComboBox *cbxFilterFunc; QPushButton *btnCalcSchematic; From 6e93dd110b4d4b0c5690cb722d07ac66ad9d6323 Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Wed, 9 Jul 2014 11:11:55 +0400 Subject: [PATCH 88/90] Implemented Bessel filter calculation --- filter.cpp | 9 +++++++++ filter.h | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/filter.cpp b/filter.cpp index df67a4c322..6472011c19 100644 --- a/filter.cpp +++ b/filter.cpp @@ -465,7 +465,16 @@ void Filter::calcCauer() // from Digital Filter Designer's handbook p.103 void Filter::calcBessel() { + Poles.clear(); + Zeros.clear(); + + if (order<=0) return; + + for (int i=0;i(BesselPoles[order-1][2*i],BesselPoles[order-1][2*i+1])); + } + reformPolesZeros(); } void Filter::calcUserTrFunc() diff --git a/filter.h b/filter.h index efc444fb37..92ac0ad9d9 100644 --- a/filter.h +++ b/filter.h @@ -34,7 +34,6 @@ class Filter enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc, User}; private: - void besselCoefficients(); void cauerOrderEstim(); void reformPolesZeros(); From af0381d5ca5d27844d1e9c40a8e1c29715f8facd Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 10 Jul 2014 13:35:34 +0400 Subject: [PATCH 89/90] Implemented interface controls disbling for Bessel filter --- filtersintez.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/filtersintez.cpp b/filtersintez.cpp index 12ceef250a..24cb425bff 100644 --- a/filtersintez.cpp +++ b/filtersintez.cpp @@ -386,7 +386,13 @@ void FilterSintez::slotSwitchParameters() cbxFilterType->setDisabled(false); } - if ((cbxFilterFunc->currentIndex()==5)) { + if ((cbxFilterFunc->currentIndex())==4) { + edtOrder->setEnabled(true); + } else { + edtOrder->setEnabled(false); + } + + if ((cbxFilterFunc->currentIndex()==5)||(cbxFilterFunc->currentIndex()==4)) { btnDefineTransferFunc->setEnabled(true); edtF2->setEnabled(false); edtPassbRpl->setEnabled(false); From 927e2ea86bfe28a9b27a49f94e8040d4f6c54b5f Mon Sep 17 00:00:00 2001 From: Vadim Kuznetzov Date: Thu, 10 Jul 2014 15:03:41 +0400 Subject: [PATCH 90/90] Added CMakeLists. Preparation for mergig with main Qucs branch started. --- .gitignore | 9 ++- CMakeLists.txt | 88 +++++++++++++++++++++++ QFilterSintez.pro | 11 +-- main.cpp | 4 +- filtersintez.cpp => qucsactivefilter.cpp | 32 ++++----- filtersintez.h => qucsactivefilter.h | 6 +- qfiltersintez.qrc => qucsactivefilter.qrc | 0 7 files changed, 123 insertions(+), 27 deletions(-) create mode 100644 CMakeLists.txt rename filtersintez.cpp => qucsactivefilter.cpp (93%) rename filtersintez.h => qucsactivefilter.h (94%) rename qfiltersintez.qrc => qucsactivefilter.qrc (100%) diff --git a/.gitignore b/.gitignore index 3e017f3124..9d1b6d2a6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *.o *.cpp~ *.h~ -QFilterSintez +qucsactivefilter *.pro.user Makefile moc_*.cpp @@ -10,3 +10,10 @@ moc_*.cpp *.dat *.dpl qrc_*.cpp +moc_*.cxx +qrc_*.cxx +CMakeFiles +CMakeCache.txt +*.cmake +*.depends + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..bc7e34db3e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,88 @@ +PROJECT(qucsactivefilter CXX C) +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +cmake_policy(VERSION 2.6) + +SET(CMAKE_BUILD_TYPE Debug) + +ADD_DEFINITIONS( -DHAVE_CONFIG_H ) + +# define variables +SET(BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin/") +SET(BITMAPDIR "${CMAKE_INSTALL_PREFIX}/share/qucs/bitmaps/") +SET(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/qucs/docs/") +SET(LANGUAGEDIR "${CMAKE_INSTALL_PREFIX}/share/qucs/lang/") +SET(LIBRARYDIR "${CMAKE_INSTALL_PREFIX}/share/qucs/library/") +SET(OCTAVEDIR "${CMAKE_INSTALL_PREFIX}/share/qucs/octave/") + +# configure the header config.h +#CONFIGURE_FILE ( +# "${PROJECT_SOURCE_DIR}/../config.h.cmake" +# "${PROJECT_BINARY_DIR}/config.h" +#) + +INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}") + +FIND_PACKAGE( Qt4 REQUIRED ) +SET( QT_USE_QTGUI TRUE ) +SET( QT_USE_QTSVG TRUE ) + +INCLUDE( ${QT_USE_FILE} ) + +ADD_DEFINITIONS(${QT_DEFINITIONS}) + +SET(QUCS-ACTIVE-FILTER_SRCS +filter.cpp +mfbfilter.cpp +main.cpp +qf_poly.cpp +sallenkey.cpp +schcauer.cpp +transferfuncdialog.cpp +qucsactivefilter.cpp +) + +SET(QUCS-ACTIVE-FILTER_MOC_HDRS +transferfuncdialog.h +qucsactivefilter.h +) + +QT4_WRAP_CPP(QUCS-ACTIVE-FILTER_MOC_SRCS ${QUCS-ACTIVE-FILTER_MOC_HDRS}) + +SET(RESOURCES qucsactivefilter.qrc) +QT4_ADD_RESOURCES(RESOURCES_SRCS ${RESOURCES}) + + +IF(APPLE) + # set information on Info.plist file + SET(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") + SET(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") + SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") + SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") + SET(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") + SET(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") + SET(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}") + SET(MACOSX_BUNDLE_COPYRIGHT "(C) 2013 Qucs team" ) + SET(MACOSX_BUNDLE_ICON_FILE qucsactivefilter.icns) + + # set where in the bundle to put the icns file + SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../qucs/bitmaps/qucsactivefilter.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + # include the icns file in the target + SET(QUCS-ACTIVE-FILTER_SRCS ${QUCS-ACTIVE-FILTER_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/../qucs/bitmaps/qucsactivefilter.icns) + +ENDIF(APPLE) + +ADD_EXECUTABLE(qucsactivefilter MACOSX_BUNDLE WIN32 + ${QUCS-ACTIVE-FILTER_SRCS} + ${QUCS-ACTIVE-FILTER_MOC_SRCS} + ${RESOURCES_SRCS} ) + +TARGET_LINK_LIBRARIES(qucsactivefilter ${QT_LIBRARIES}) + +INSTALL(TARGETS qucsactivefilter + BUNDLE DESTINATION bin COMPONENT Runtime + RUNTIME DESTINATION bin COMPONENT Runtime + ) + +# man pages +INSTALL( FILES qucsactivefilter.1 DESTINATION share/man/man1 ) + diff --git a/QFilterSintez.pro b/QFilterSintez.pro index d8533cbadc..b69cf10613 100644 --- a/QFilterSintez.pro +++ b/QFilterSintez.pro @@ -13,15 +13,15 @@ TEMPLATE = app SOURCES += main.cpp\ - filtersintez.cpp \ filter.cpp \ sallenkey.cpp \ mfbfilter.cpp \ qf_poly.cpp \ schcauer.cpp \ - transferfuncdialog.cpp + transferfuncdialog.cpp \ + qucsactivefilter.cpp -HEADERS += filtersintez.h \ +HEADERS += \ filter.h \ sallenkey.h \ mfbfilter.h \ @@ -29,7 +29,8 @@ HEADERS += filtersintez.h \ qf_matrix.h \ schcauer.h \ transferfuncdialog.h \ - bessel.h + bessel.h \ + qucsactivefilter.h RESOURCES += \ - qfiltersintez.qrc + qucsactivefilter.qrc diff --git a/main.cpp b/main.cpp index d26784a60a..3de11badd7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,10 +1,10 @@ #include -#include "filtersintez.h" +#include "qucsactivefilter.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); - FilterSintez w; + QucsActiveFilter w; w.show(); return a.exec(); diff --git a/filtersintez.cpp b/qucsactivefilter.cpp similarity index 93% rename from filtersintez.cpp rename to qucsactivefilter.cpp index 24cb425bff..beed449f9f 100644 --- a/filtersintez.cpp +++ b/qucsactivefilter.cpp @@ -1,4 +1,4 @@ -#include "filtersintez.h" +#include "qucsactivefilter.h" #include "sallenkey.h" #include "mfbfilter.h" #include "schcauer.h" @@ -6,7 +6,7 @@ #include -FilterSintez::FilterSintez(QWidget *parent) +QucsActiveFilter::QucsActiveFilter(QWidget *parent) : QMainWindow(parent) { Nfil = 4; @@ -16,13 +16,13 @@ FilterSintez::FilterSintez(QWidget *parent) QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); //lblInputData = new QLabel(tr("Входные данные")); - lblA1 = new QLabel(tr("Passband attenuation, Ap")); - lblA2 = new QLabel(tr("Stopband attenuation, As")); - lblF1 = new QLabel(tr("Cuttof frequency, Fc (Гц)")); - lblF2 = new QLabel(tr("Stopband frequency, Fs (Гц)")); - lblRpl1 = new QLabel(tr("Passband ripple Rp(дБ)")); - //lblRpl2 = new QLabel(tr("Stopband ripple (дБ)")); - lblKv = new QLabel(tr("Passband gain, Kv (дБ)")); + lblA1 = new QLabel(tr("Passband attenuation, Ap (dB)")); + lblA2 = new QLabel(tr("Stopband attenuation, As (dB)")); + lblF1 = new QLabel(tr("Cuttof frequency, Fc (Hz)")); + lblF2 = new QLabel(tr("Stopband frequency, Fs (Hz)")); + lblRpl1 = new QLabel(tr("Passband ripple Rp(dB)")); + //lblRpl2 = new QLabel(tr("Stopband ripple (dB)")); + lblKv = new QLabel(tr("Passband gain, Kv (dB)")); edtA1 = new QLineEdit("3"); @@ -173,13 +173,13 @@ FilterSintez::FilterSintez(QWidget *parent) zenter->setLayout(top1); } -FilterSintez::~FilterSintez() +QucsActiveFilter::~QucsActiveFilter() { } -void FilterSintez::slotCalcSchematic() +void QucsActiveFilter::slotCalcSchematic() { FilterParam par; @@ -306,7 +306,7 @@ void FilterSintez::slotCalcSchematic() } -void FilterSintez::slotUpdateResponse() +void QucsActiveFilter::slotUpdateResponse() { QString s = ":/images/AFR.svg"; @@ -335,7 +335,7 @@ void FilterSintez::slotUpdateResponse() imgAFR->setFixedSize(sz); } -void FilterSintez::slotUpdateSchematic() +void QucsActiveFilter::slotUpdateSchematic() { slotUpdateResponse(); QString s; @@ -369,7 +369,7 @@ void FilterSintez::slotUpdateSchematic() sch_pic->setFixedSize(sz); } -void FilterSintez::slotSwitchParameters() +void QucsActiveFilter::slotSwitchParameters() { if (cbxFilterFunc->currentIndex()==0) { edtA1->setEnabled(true); @@ -409,7 +409,7 @@ void FilterSintez::slotSwitchParameters() } } -void FilterSintez::slotDefineTransferFunc() +void QucsActiveFilter::slotDefineTransferFunc() { TransferFuncDialog *trfuncdlg = new TransferFuncDialog(coeffA,coeffB,this); @@ -419,7 +419,7 @@ void FilterSintez::slotDefineTransferFunc() delete trfuncdlg; } -void FilterSintez::errorMessage(QString str) +void QucsActiveFilter::errorMessage(QString str) { QMessageBox* msg = new QMessageBox(QMessageBox::Critical,tr("Active filter design"), str, diff --git a/filtersintez.h b/qucsactivefilter.h similarity index 94% rename from filtersintez.h rename to qucsactivefilter.h index 2ef7097fe4..b848c36172 100644 --- a/filtersintez.h +++ b/qucsactivefilter.h @@ -7,7 +7,7 @@ #include #include "filter.h" -class FilterSintez : public QMainWindow +class QucsActiveFilter : public QMainWindow { Q_OBJECT @@ -88,8 +88,8 @@ private slots: void slotDefineTransferFunc(); public: - FilterSintez(QWidget *parent = 0); - ~FilterSintez(); + QucsActiveFilter(QWidget *parent = 0); + ~QucsActiveFilter(); }; #endif // FILTERSINTEZ_H diff --git a/qfiltersintez.qrc b/qucsactivefilter.qrc similarity index 100% rename from qfiltersintez.qrc rename to qucsactivefilter.qrc