use same convention for directory name
* Use `qucs-[name of tool]` for directory
@ -36,6 +36,7 @@ SUBDIRS = \
|
||||
qucs-help \
|
||||
qucs-lib \
|
||||
qucs-transcalc \
|
||||
qucs-activefilter \
|
||||
qucs-rescodes \
|
||||
contrib \
|
||||
$(FILTERV2) \
|
||||
@ -48,7 +49,7 @@ if COND_MACOSX
|
||||
app_PROGS = $(top_builddir)/qucs/qucs \
|
||||
$(top_builddir)/qucs-attenuator/qucsattenuator \
|
||||
$(top_builddir)/qucs-filter/qucsfilter \
|
||||
$(top_builddir)/qucsactivefilter/qucsactivefilter \
|
||||
$(top_builddir)/qucs-activefilter/qucsactivefilter \
|
||||
$(top_builddir)/qucs-help/qucshelp \
|
||||
$(top_builddir)/qucs-lib/qucslib \
|
||||
$(top_builddir)/qucs-edit/qucsedit \
|
||||
|
@ -801,7 +801,7 @@ AC_CONFIG_FILES([Makefile
|
||||
qucs-help/docs/cs/Makefile
|
||||
qucs-help/docs/pt/Makefile
|
||||
qucs-filter/Makefile
|
||||
qucsactivefilter/Makefile
|
||||
qucs-activefilter/Makefile
|
||||
qucs-transcalc/Makefile
|
||||
qucs-transcalc/examples/Makefile
|
||||
qucs-lib/Makefile
|
||||
|
19
qucs-activefilter/.gitignore
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
*.o
|
||||
*.cpp~
|
||||
*.h~
|
||||
qucsactivefilter
|
||||
*.pro.user
|
||||
Makefile
|
||||
moc_*.cpp
|
||||
*.sch
|
||||
*.sch~
|
||||
*.dat
|
||||
*.dpl
|
||||
qrc_*.cpp
|
||||
moc_*.cxx
|
||||
qrc_*.cxx
|
||||
CMakeFiles
|
||||
CMakeCache.txt
|
||||
*.cmake
|
||||
*.depends
|
||||
|
401
qucs-activefilter/AFR.svg
Normal file
@ -0,0 +1,401 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="196.69392"
|
||||
height="170.28023"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="AFR.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3763"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3766"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3766-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker5927"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5929"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:cx="82.130173"
|
||||
inkscape:cy="77.007002"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="722"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="1020"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2985"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
units="mm"
|
||||
spacingx="1mm"
|
||||
spacingy="1mm"
|
||||
originx="-1.0477027mm"
|
||||
originy="-247.40872mm" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-3.7123325,-5.4368782)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 17.716535,148.81888 0,-124.015753 3.543308,10.629916"
|
||||
id="path2987"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 17.716535,148.81888 159.448815,0 -10.62992,-3.54332"
|
||||
id="path3757"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 17.716535,60.236198 c 6.484394,-6.437719 9.867912,-11.024065 17.716536,-10.629921 7.848624,0.394144 12.081982,10.544488 17.716535,10.629921 5.634553,0.08543 8.026167,-9.970094 17.716536,-10.629921 9.690369,-0.659827 15.13139,5.196517 17.716535,10.629921 l 17.716533,88.582682 c 0.24254,-9.7986 2.43977,-17.40295 17.71654,-17.71654 9.3354,0.36517 16.92556,4.05746 17.71653,17.71654 1.01915,-11.28051 7.17493,-16.91073 17.71654,-17.71654"
|
||||
id="path4385"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="czzzccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 70.866142,49.606277 53.149608,0"
|
||||
id="path4387"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.63245553px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 35.433071,49.606277 14.173228,0"
|
||||
id="path4389"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 46.062992,28.346435 0,21.259842 3.543307,-10.629927"
|
||||
id="path4391"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 46.062992,77.952734 0,-17.716536"
|
||||
id="path4575"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 46.062992,49.606277 0,10.629921"
|
||||
id="path4759"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="24.80315"
|
||||
y="74.409424"
|
||||
id="text4761"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4763"
|
||||
x="24.80315"
|
||||
y="74.409424">Rp</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 88.582677,60.236198 0,46.062992"
|
||||
id="path4765"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 17.716535,102.75588 70.866142,0"
|
||||
id="path4767"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="45.714287"
|
||||
y="94.862183"
|
||||
id="text5139"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5141"
|
||||
x="45.714287"
|
||||
y="94.862183">Fc</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 17.716535,148.81888 0,17.71653"
|
||||
id="path5143"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 99.212598,113.3858 0,53.14961"
|
||||
id="path5147"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 99.212598,162.9921 -81.496063,0 10.629922,-3.54331"
|
||||
id="path5149"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="50.714287"
|
||||
y="175.57648"
|
||||
id="text5519"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5521"
|
||||
x="50.714287"
|
||||
y="175.57648">Fs</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 70.866142,49.606277 92.125988,0"
|
||||
id="path5523"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 99.212598,113.3858 63.779532,0"
|
||||
id="path5525"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 159.44882,113.3858 0,-63.779523 3.54331,10.629915"
|
||||
id="path5527"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="165.71429"
|
||||
y="86.647896"
|
||||
id="text5897"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5899"
|
||||
x="165.71429"
|
||||
y="86.647896">As</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="17.716536"
|
||||
y="14.173206"
|
||||
id="text5901"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5903"
|
||||
x="17.716536"
|
||||
y="14.173206">K (dB)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="167.5"
|
||||
y="167.36218"
|
||||
id="text5905"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5907"
|
||||
x="167.5"
|
||||
y="167.36218">F (Hz)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="3.2142856"
|
||||
y="152.00504"
|
||||
id="text5909"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5911"
|
||||
x="3.2142856"
|
||||
y="152.00504">0</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 42.519685,60.236198 10.629921,0"
|
||||
id="path5913"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.63245553px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 92.125986,49.606277 14.173234,0"
|
||||
id="path4389-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 102.75591,28.346435 0,21.259842 3.5433,-10.629927"
|
||||
id="path4391-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 102.75591,77.952734 0,-17.716536 3.5433,10.629916"
|
||||
id="path4575-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 102.75591,49.606277 0,10.629921"
|
||||
id="path4759-3"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="113.38583"
|
||||
y="60.236198"
|
||||
id="text4761-6"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4763-4"
|
||||
x="113.38583"
|
||||
y="60.236198">Ap</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 88.582677,60.236198 17.716533,0"
|
||||
id="path5965"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 24.634124,93.775692 -10.629921,3.543307 10.629921,3.543311"
|
||||
id="path6381"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 74.240424,100.86231 84.870345,97.318999 74.240424,93.775692"
|
||||
id="path6383"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 38.807353,33.539472 42.35066,44.169393"
|
||||
id="path6761"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 45.893967,65.429236 42.35066,54.799314 38.807353,65.429236"
|
||||
id="path6763"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 14.004203,19.366243 10.460896,29.996165"
|
||||
id="path7141"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 14.004203,157.55522 10.629921,3.54331"
|
||||
id="path7519"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 84.870345,154.01191 10.629921,3.54331 -10.629921,3.54331"
|
||||
id="path7521"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 173.45302,143.38199 162.8231,146.9253"
|
||||
id="path7711"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 99.043573,54.799314 95.500266,65.429236"
|
||||
id="path7901"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 99.043573,44.169393 95.500266,33.539472"
|
||||
id="path8091"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 155.73649,44.169393 -3.54331,10.629921"
|
||||
id="path8657"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 159.27979,97.318999 -3.5433,10.629921 -3.54331,-10.629921"
|
||||
id="path8659"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
96
qucs-activefilter/CMakeLists.txt
Normal file
@ -0,0 +1,96 @@
|
||||
PROJECT(qucsactivefilter CXX C)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
cmake_policy(VERSION 2.6)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR "0")
|
||||
set(PROJECT_VERSION_MINOR "0")
|
||||
set(PROJECT_VERSION_PATCH "18")
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
set(PROJECT_VENDOR "Qucs team. This program is licensed under the GNU GPL")
|
||||
set(PROJECT_COPYRIGHT_YEAR "2014")
|
||||
set(PROJECT_DOMAIN_FIRST "qucs")
|
||||
set(PROJECT_DOMAIN_SECOND "org")
|
||||
|
||||
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_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 )
|
||||
|
2
qucs-activefilter/README
Normal file
@ -0,0 +1,2 @@
|
||||
QucsActiveFilter is tool for sintezing active and passive analog filters.
|
||||
|
57
qucs-activefilter/bessel-poles.m
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/octave -qf
|
||||
|
||||
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);
|
||||
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");
|
73
qucs-activefilter/bessel.h
Normal file
@ -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
|
1595
qucs-activefilter/cauer.svg
Normal file
After Width: | Height: | Size: 52 KiB |
561
qucs-activefilter/filter.cpp
Normal file
@ -0,0 +1,561 @@
|
||||
/***************************************************************************
|
||||
filter.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "filter.h"
|
||||
#include "qf_poly.h"
|
||||
#include "bessel.h"
|
||||
|
||||
Filter::Filter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par)
|
||||
{
|
||||
ffunc = ffunc_;
|
||||
ftype = type_;
|
||||
Fc = par.Fc;
|
||||
Fs = par.Fs;
|
||||
Rp = par.Rp;
|
||||
As = par.As;
|
||||
Ap = par.Ap;
|
||||
Kv = par.Kv;
|
||||
if (ffunc==Filter::Bessel) {
|
||||
order = par.order;
|
||||
}
|
||||
}
|
||||
|
||||
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<<s;
|
||||
sch.close();*/
|
||||
}
|
||||
|
||||
void Filter::createHighPassSchematic(QString &s)
|
||||
{
|
||||
s = "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
}
|
||||
|
||||
void Filter::createLowPassSchematic(QString &s)
|
||||
{
|
||||
s = "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
}
|
||||
|
||||
bool Filter::calcFilter()
|
||||
{
|
||||
Sections.clear();
|
||||
Poles.clear();
|
||||
Zeros.clear();
|
||||
|
||||
switch (ffunc) {
|
||||
case Filter::Chebyshev : calcChebyshev();
|
||||
break;
|
||||
case Filter::Butterworth : calcButterworth();
|
||||
break;
|
||||
case Filter::Cauer : calcCauer();
|
||||
break;
|
||||
case Filter::InvChebyshev : calcInvChebyshev();
|
||||
break;
|
||||
case Filter::Bessel : calcBessel();
|
||||
break;
|
||||
case Filter::User : calcUserTrFunc();
|
||||
break;
|
||||
default :
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Poles.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((ffunc==Filter::Cauer)||
|
||||
(ffunc==Filter::InvChebyshev))
|
||||
&&(Zeros.isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ftype) {
|
||||
case Filter::LowPass : calcLowPass();
|
||||
break;
|
||||
case Filter::HighPass : calcHighPass();
|
||||
break;
|
||||
default: return false;
|
||||
break;
|
||||
}
|
||||
|
||||
bool res = checkRCL();
|
||||
|
||||
Nr = Nr1*(order/2);
|
||||
Nc = Nc1*(order/2);
|
||||
Nopamp = Nop1*order/2;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void Filter::calcHighPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Filter::calcLowPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Filter::calcFirstOrder()
|
||||
{
|
||||
if (order%2 != 0) {
|
||||
|
||||
float R1, R2,R3;
|
||||
|
||||
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();
|
||||
//float C = re*re + im*im;
|
||||
float C = -re;
|
||||
float C1 = 10/Fc;
|
||||
|
||||
if (ftype==Filter::HighPass) {
|
||||
R1 = 1.0*C/(Wc*C1);
|
||||
} else {
|
||||
R1 = 1.0/(Wc*C*C1);
|
||||
}
|
||||
|
||||
qDebug()<<C;
|
||||
|
||||
if (Kv != 1.0) {
|
||||
R2 = Kv*R1/(Kv - 1);
|
||||
R3 = Kv*R1;
|
||||
} else {
|
||||
R2 = 1.0;
|
||||
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;
|
||||
Sections.append(curr_stage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Filter::createPartList(QStringList &lst)
|
||||
{
|
||||
lst<<QObject::tr("Part list");
|
||||
if ((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer)) {
|
||||
lst<<"Stage# C1(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm) R5(kOhm)";
|
||||
} else {
|
||||
lst<<"Stage# C1(uF) C2(uF) R1(kOhm) R2(kOhm) R3(kOhm) R4(kOhm)";
|
||||
}
|
||||
|
||||
RC_elements stage;
|
||||
|
||||
foreach (stage,Sections) {
|
||||
QString suff1,suff2;
|
||||
float C1=autoscaleCapacitor(stage.C1,suff1);
|
||||
float C2=autoscaleCapacitor(stage.C2,suff2);
|
||||
if ((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer)) {
|
||||
lst<<QString("%1%2%3%4%5%6%7%8").arg(stage.N,6).arg(C1,10,'f',3).arg(suff1)
|
||||
.arg(stage.R1,10,'f',3).arg(stage.R2,10,'f',3).arg(stage.R3,10,'f',3).arg(stage.R4,10,'f',3).arg(stage.R5,10,'f',3);
|
||||
} else {
|
||||
lst<<QString("%1%2%3%4%5%6%7%8%9").arg(stage.N,6).arg(C1,10,'f',3).arg(suff1).arg(C2,10,'f',3).arg(suff2)
|
||||
.arg(stage.R1,10,'f',3).arg(stage.R2,10,'f',3).arg(stage.R3,10,'f',3).arg(stage.R4,10,'f',3);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Filter::createPolesZerosList(QStringList &lst)
|
||||
{
|
||||
lst<<QString(QObject::tr("Filter order = %1")).arg(order);
|
||||
if (!Zeros.isEmpty()) {
|
||||
lst<<""<<QObject::tr("Zeros list Pk=Re+j*Im");
|
||||
std::complex<float> zero;
|
||||
foreach(zero,Zeros) {
|
||||
lst<<QString::number(zero.real()) + " + j*" + QString::number(zero.imag());
|
||||
}
|
||||
}
|
||||
lst<<""<<QObject::tr("Poles list Pk=Re+j*Im");
|
||||
std::complex<float> pole;
|
||||
foreach(pole,Poles) {
|
||||
lst<<QString::number(pole.real()) + " + j*" + QString::number(pole.imag());
|
||||
}
|
||||
lst<<"";
|
||||
}
|
||||
|
||||
void Filter::createFirstOrderComponentsHPF(QString &s,RC_elements stage,int dx)
|
||||
{
|
||||
QString suf;
|
||||
float C1 = autoscaleCapacitor(stage.C1,suf);
|
||||
s += QString("<OpAmp OP%1 1 %2 160 -26 42 0 0 \"1e6\" 1 \"15 V\" 0>\n").arg(Nopamp+1).arg(270+dx);
|
||||
s += QString("<GND * 1 %1 270 0 0 0 0>\n").arg(170+dx);
|
||||
s += QString("<GND * 1 %1 370 0 0 0 0>\n").arg(220+dx);
|
||||
s += QString("<R R%1 1 %2 340 15 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(Nr+2).arg(220+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 240 -75 -26 1 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(Nr+1).arg(170+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 260 -26 15 1 2 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(Nr+3).arg(310+dx).arg(stage.R3,0,'f',3);
|
||||
s += QString("<C C%1 1 %2 190 -26 -45 1 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\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("<OpAmp OP%1 1 %2 160 -26 42 0 0 \"1e6\" 1 \"15 V\" 0>\n").arg(Nopamp+1).arg(270+dx);
|
||||
s += QString("<GND * 1 %1 270 0 0 0 0>\n").arg(170+dx);
|
||||
s += QString("<GND * 1 %1 370 0 0 0 0>\n").arg(220+dx);
|
||||
s += QString("<R R%1 1 %2 340 15 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(Nr+2).arg(220+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 190 -75 -52 1 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(Nr+1).arg(100+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 260 -26 15 1 2 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(Nr+3).arg(310+dx).arg(stage.R3,0,'f',3);
|
||||
s += QString("<C C%1 1 %2 240 26 -45 1 1 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(Nc+1).arg(170+dx).arg(C1,0,'f',3).arg(suf);
|
||||
}
|
||||
|
||||
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 %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);
|
||||
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";
|
||||
C1 *= 1e6;
|
||||
}
|
||||
|
||||
if ((C1<1e-7)&&(C1>=1e-8)) {
|
||||
suffix = "nF";
|
||||
C1 *= 1e9;
|
||||
}
|
||||
|
||||
if (C1<1e-8) {
|
||||
suffix = "pF";
|
||||
C1 *= 1e12;
|
||||
}
|
||||
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()
|
||||
{
|
||||
float kf = std::max(Fs/Fc,Fc/Fs);
|
||||
float eps=sqrt(pow(10,0.1*Rp)-1);
|
||||
|
||||
float N1 = acosh(sqrt((pow(10,0.1*As)-1)/(eps*eps)))/acosh(kf);
|
||||
int N = ceil(N1);
|
||||
|
||||
float a = sinh((asinh(1/eps))/N);
|
||||
float b = cosh((asinh(1/eps))/N);
|
||||
|
||||
Poles.clear();
|
||||
Zeros.clear();
|
||||
|
||||
for (int k=1;k<=N;k++) {
|
||||
float re = -1*a*sin(M_PI*(2*k-1)/(2*N));
|
||||
float im = b*cos(M_PI*(2*k-1)/(2*N));
|
||||
std::complex<float> pol(re,im);
|
||||
Poles.append(pol);
|
||||
}
|
||||
|
||||
order = Poles.count();
|
||||
}
|
||||
|
||||
void Filter::calcButterworth()
|
||||
{
|
||||
float kf = std::min(Fc/Fs,Fs/Fc);
|
||||
|
||||
float C1=(pow(10,(0.1*Ap))-1)/(pow(10,(0.1*As))-1);
|
||||
float J2=log10(C1)/(2*log10(kf));
|
||||
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<float> pol(re,im);
|
||||
Poles.append(pol);
|
||||
}
|
||||
|
||||
order = Poles.count();
|
||||
}
|
||||
|
||||
void Filter::calcInvChebyshev() // Chebyshev Type-II filter
|
||||
{
|
||||
Poles.clear();
|
||||
Zeros.clear();
|
||||
|
||||
float kf = std::max(Fs/Fc,Fc/Fs);
|
||||
|
||||
order = ceil(acosh(sqrt(pow(10.0,0.1*As)-1.0))/acosh(kf));
|
||||
|
||||
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<float>(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<float> invpol(re,im); // inverse pole
|
||||
std::complex<float> pol;
|
||||
pol = std::complex<float>(1.0,0) / invpol; // pole
|
||||
Poles.append(pol);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Filter::cauerOrderEstim() // from Digital Filter Design Handbook page 102
|
||||
{
|
||||
float k = std::min(Fc/Fs,Fs/Fc);
|
||||
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;
|
||||
}
|
||||
|
||||
if (order%2!=0) {
|
||||
cc[order-1] = P0; // first order section
|
||||
bb[order-1] = 0;
|
||||
}
|
||||
|
||||
Zeros.clear();
|
||||
Poles.clear();
|
||||
for (int i=0;i<r;i++) {
|
||||
float im = sqrt(aa[i]);
|
||||
Zeros.append(std::complex<float>(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<float>(re,im));
|
||||
}
|
||||
|
||||
if (order%2!=0) {
|
||||
Poles.append(std::complex<float>(-cc[order-1],0.0));
|
||||
}
|
||||
|
||||
for (int i=r-1;i>=0;i--) {
|
||||
float im = sqrt(aa[i]);
|
||||
Zeros.append(std::complex<float>(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<float>(re,-im));
|
||||
}
|
||||
}
|
||||
|
||||
void Filter::calcBessel()
|
||||
{
|
||||
Poles.clear();
|
||||
Zeros.clear();
|
||||
|
||||
if (order<=0) return;
|
||||
|
||||
for (int i=0;i<order;i++) {
|
||||
Poles.append(std::complex<float>(BesselPoles[order-1][2*i],BesselPoles[order-1][2*i+1]));
|
||||
}
|
||||
|
||||
reformPolesZeros();
|
||||
}
|
||||
|
||||
void Filter::calcUserTrFunc()
|
||||
{
|
||||
if ((!vec_A.isEmpty())&&(!vec_B.isEmpty())) {
|
||||
long double *a = vec_A.data();
|
||||
long double *b = vec_B.data();
|
||||
|
||||
int a_order = vec_A.count() - 1;
|
||||
int b_order = vec_B.count() - 1;
|
||||
|
||||
order = std::max(a_order,b_order);
|
||||
|
||||
qf_poly Numenator(b_order,b);
|
||||
qf_poly Denomenator(a_order,a);
|
||||
|
||||
Numenator.to_roots();
|
||||
Denomenator.to_roots();
|
||||
|
||||
Numenator.disp_c();
|
||||
Denomenator.disp_c();
|
||||
|
||||
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<Np/2;i++) {
|
||||
if ((i%2)!=0) {
|
||||
std::complex<float> tmp;
|
||||
tmp = Poles[i];
|
||||
Poles[i]=Poles[Np-1-i];
|
||||
Poles[Np-1-i]=tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<Nz/2;i++) {
|
||||
if ((i%2)!=0) {
|
||||
std::complex<float> tmp;
|
||||
tmp = Poles[i];
|
||||
Poles[i]=Poles[Nz-1-i];
|
||||
Poles[Nz-1-i]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Filter::set_TrFunc(QVector<long double> a, QVector<long double> b)
|
||||
{
|
||||
vec_A = a;
|
||||
vec_B = b;
|
||||
}
|
108
qucs-activefilter/filter.h
Normal file
@ -0,0 +1,108 @@
|
||||
/***************************************************************************
|
||||
filter.h
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 FILTER_H
|
||||
#define FILTER_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <math.h>
|
||||
#include <complex>
|
||||
|
||||
struct RC_elements {
|
||||
int N;
|
||||
float R1;
|
||||
float R2;
|
||||
float R3;
|
||||
float R4;
|
||||
float R5;
|
||||
float C1;
|
||||
float C2;
|
||||
};
|
||||
|
||||
struct FilterParam {
|
||||
float Ap;
|
||||
float As;
|
||||
float Fc;
|
||||
float Fs;
|
||||
float Rp;
|
||||
float Kv;
|
||||
int order;
|
||||
};
|
||||
|
||||
class Filter
|
||||
{
|
||||
|
||||
public:
|
||||
enum FType {HighPass, LowPass, BandPass, BandStop, NoFilter};
|
||||
enum FilterFunc {Butterworth, Chebyshev, Cauer, Bessel, InvChebyshev, NoFunc, User};
|
||||
|
||||
private:
|
||||
void cauerOrderEstim();
|
||||
void reformPolesZeros();
|
||||
|
||||
protected:
|
||||
QVector< std::complex<float> > Poles;
|
||||
QVector< std::complex<float> > Zeros;
|
||||
QVector<long double> vec_B; // Transfer function numenator
|
||||
QVector<long double> vec_A; // and denominator
|
||||
QVector<RC_elements> Sections;
|
||||
|
||||
Filter::FType ftype;
|
||||
Filter::FilterFunc ffunc;
|
||||
int order;
|
||||
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 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);
|
||||
void createFirstOrderComponentsLPF(QString &s,RC_elements stage, int dx);
|
||||
void createFirstOrderWires(QString &s, int dx, int y);
|
||||
float autoscaleCapacitor(float C, QString &suffix);
|
||||
virtual void calcHighPass();
|
||||
virtual void calcLowPass();
|
||||
virtual void createHighPassSchematic(QString &s);
|
||||
virtual void createLowPassSchematic(QString &s);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
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);
|
||||
|
||||
virtual bool calcFilter();
|
||||
|
||||
void set_TrFunc(QVector<long double> a, QVector<long double> b);
|
||||
|
||||
};
|
||||
|
||||
#endif // FILTER_H
|
393
qucs-activefilter/high-pass.svg
Normal file
@ -0,0 +1,393 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="196.69392"
|
||||
height="170.28023"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="high-pass.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3763"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3766"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3766-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker5927"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5929"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.959798"
|
||||
inkscape:cx="82.130173"
|
||||
inkscape:cy="91.203431"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="722"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="1020"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2985"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
units="mm"
|
||||
spacingx="1mm"
|
||||
spacingy="1mm"
|
||||
originx="-1.0477027mm"
|
||||
originy="-247.40872mm" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-3.7123325,-5.4368782)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 17.716535,148.81888 0,-124.015753 3.543308,10.629916"
|
||||
id="path2987"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 17.716535,148.81888 159.448815,0 -10.62992,-3.54332"
|
||||
id="path3757"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 159.44882,60.236198 c -6.48439,-6.437719 -9.86791,-11.024065 -17.71654,-10.629921 -7.84862,0.394144 -12.08198,10.544488 -17.71653,10.629921 -5.63455,0.08543 -8.02617,-9.970094 -17.71654,-10.629921 C 96.608844,48.94645 91.167823,54.802794 88.582678,60.236198 L 70.866145,148.81888 c -0.24254,-9.7986 -2.43977,-17.40295 -17.71654,-17.71654 -9.3354,0.36517 -16.92556,4.05746 -17.71653,17.71654 -1.01915,-11.28051 -7.17493,-16.91073 -17.71654,-17.71654"
|
||||
id="path4385"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="czzzccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 70.866142,49.606277 53.149608,0"
|
||||
id="path4387"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.00000036px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 177.16535,49.606271 -35.43307,0"
|
||||
id="path4389"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 116.92914,28.346434 0,21.259842 3.5433,-10.629927"
|
||||
id="path4391"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 116.92914,77.952733 0,-17.716536"
|
||||
id="path4575"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 116.92914,49.606276 0,10.629921"
|
||||
id="path4759"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="120.47244"
|
||||
y="74.409424"
|
||||
id="text4761"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4763"
|
||||
x="120.47244"
|
||||
y="74.409424">Rp</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.87705797px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 88.582677,60.236198 0,35.433065"
|
||||
id="path4765"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 17.716535,92.125959 70.866142,0"
|
||||
id="path4767"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="46.062992"
|
||||
y="88.582649"
|
||||
id="text5139"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5141"
|
||||
x="46.062992"
|
||||
y="88.582649">Fc</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 17.716535,148.81888 0,17.71653"
|
||||
id="path5143"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 77.952756,113.3858 0,53.14961"
|
||||
id="path5147"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.85972697px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 77.952756,162.9921 -60.236221,0 7.856899,-3.54331"
|
||||
id="path5149"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="42.519684"
|
||||
y="173.62202"
|
||||
id="text5519"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5521"
|
||||
x="42.519684"
|
||||
y="173.62202">Fs</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.62017363px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 70.866142,49.606277 35.433068,0"
|
||||
id="path5523"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:none"
|
||||
d="m 173.62204,113.3858 0,-63.779522 3.54331,10.629915"
|
||||
id="path5527"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="179.88751"
|
||||
y="86.647896"
|
||||
id="text5897"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5899"
|
||||
x="179.88751"
|
||||
y="86.647896">As</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="17.716536"
|
||||
y="17.716507"
|
||||
id="text5901"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5903"
|
||||
x="17.716536"
|
||||
y="17.716507">K (dB)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="162.99213"
|
||||
y="166.5354"
|
||||
id="text5905"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5907"
|
||||
x="162.99213"
|
||||
y="166.5354">F (Hz)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="7.0866141"
|
||||
y="152.36218"
|
||||
id="text5909"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5911"
|
||||
x="7.0866141"
|
||||
y="152.36218">0</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 113.38583,60.236197 10.62992,0"
|
||||
id="path5913"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.63245553px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 92.125986,49.606277 14.173234,0"
|
||||
id="path4389-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 74.409453,28.346435 0,21.259842 3.5433,-10.629927"
|
||||
id="path4391-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
|
||||
d="m 74.409453,77.952734 0,-17.716536 3.5433,10.629916"
|
||||
id="path4575-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 74.409453,49.606277 0,10.629921"
|
||||
id="path4759-3"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="53.149605"
|
||||
y="56.692886"
|
||||
id="text4761-6"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4763-4"
|
||||
x="53.149605"
|
||||
y="56.692886">Ap</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.09544528px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 70.866142,60.236198 21.259842,0"
|
||||
id="path5965"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 28.346456,88.582649 -10.629921,3.543307 10.629921,3.543311"
|
||||
id="path6381"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 77.952756,95.669267 88.582677,92.125956 77.952756,88.582649"
|
||||
id="path6383"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 113.38583,38.97635 3.54331,10.629921"
|
||||
id="path6761"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 120.47244,70.866114 -3.5433,-10.629922 -3.54331,10.629922"
|
||||
id="path6763"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 14.004203,19.366243 10.460896,29.996165"
|
||||
id="path7141"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 14.004203,157.55522 10.629921,3.54331"
|
||||
id="path7519"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 67.322836,159.44879 10.629921,3.54331 -10.629921,3.54331"
|
||||
id="path7521"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 173.45302,143.38199 162.8231,146.9253"
|
||||
id="path7711"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 74.409449,60.236192 70.866142,70.866114"
|
||||
id="path7901"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 74.409449,49.606271 70.866142,38.97635"
|
||||
id="path8091"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 173.62205,49.606272 -3.54331,10.629921"
|
||||
id="path8657"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 177.16535,102.75588 -3.5433,10.62992 -3.54331,-10.62992"
|
||||
id="path8659"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 74.240424,107.94892 99.212596,0"
|
||||
id="path3051"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(3.7123325,5.4368782)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
28
qucs-activefilter/main.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/***************************************************************************
|
||||
main.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 <QApplication>
|
||||
#include "qucsactivefilter.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QucsActiveFilter w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
1050
qucs-activefilter/mfb-highpass.svg
Normal file
After Width: | Height: | Size: 35 KiB |
1053
qucs-activefilter/mfb-lowpass.svg
Normal file
After Width: | Height: | Size: 35 KiB |
264
qucs-activefilter/mfbfilter.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
/***************************************************************************
|
||||
mfbfilter.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "mfbfilter.h"
|
||||
|
||||
MFBfilter::MFBfilter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par)
|
||||
: Filter(ffunc_,type_,par)
|
||||
{
|
||||
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::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 = order/2; // number of 2-nd order stages
|
||||
int N1stOrd = order%2; // number of 1-st order stages
|
||||
|
||||
s += "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
s += "<Components>\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 += "<Eqn Eqn1 1 610 450 -30 14 0 0 \"K=dB(out.v/in.v)\" 1 \"yes\" 0>\n";
|
||||
s += QString("<Vac V1 1 %1 330 18 -26 0 1 \"1 V\" 1 \"1 kHz\" 0 \"0\" 0 \"0\" 0>\n").arg(70+dx);
|
||||
s += QString("<GND * 1 %1 360 0 0 0 0>\n").arg(70+dx);
|
||||
for (int i=1; i<=N2ord; i++) {
|
||||
stage = Sections.at(i-1);
|
||||
qDebug()<<stage.N;
|
||||
QString suffix1, suffix2;
|
||||
float C1 = autoscaleCapacitor(stage.C1,suffix1);
|
||||
float C2 = autoscaleCapacitor(stage.C2,suffix2);
|
||||
s += QString("<GND * 1 %1 380 0 0 0 0>\n").arg(200+dx);
|
||||
s += QString("<GND * 1 %1 350 0 0 0 0>\n").arg(360+dx);
|
||||
s += QString("<OpAmp OP%1 1 %2 270 -26 -70 1 0 \"1e6\" 1 \"15 V\" 0>\n").arg(1+(i-1)*Nop1).arg(390+dx);
|
||||
s += QString("<C C%1 1 %2 350 17 -26 0 1 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(2+(i-1)*Nc1).arg(200+dx).arg(C2,0,'f',3).arg(suffix2);
|
||||
s += QString("<C C%1 1 %2 180 17 -26 0 1 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(1+(i-1)*Nc1).arg(320+dx).arg(C1,0,'f',3).arg(suffix1);
|
||||
s += QString("<R R%1 1 %2 180 15 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(1+(i-1)*Nr1).arg(200+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 250 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(2+(i-1)*Nr1).arg(150+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 250 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(3+(i-1)*Nr1).arg(250+dx).arg(stage.R3,0,'f',3);
|
||||
dx += 510;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
createFirstOrderComponentsLPF(s,Sections.last(),dx+10);
|
||||
}
|
||||
|
||||
s += "</Components>\n";
|
||||
s += "<Wires>\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)==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);
|
||||
}
|
||||
dx += 510;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
createFirstOrderWires(s,dx+10,270);
|
||||
}
|
||||
|
||||
s += "</Wires>\n";
|
||||
}
|
||||
|
||||
void MFBfilter::createHighPassSchematic(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 += "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
s += "<Components>\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 += "<Eqn Eqn1 1 610 450 -30 14 0 0 \"K=dB(out.v/in.v)\" 1 \"yes\" 0>\n";
|
||||
s += QString("<Vac V1 1 %1 330 18 -26 0 1 \"1 V\" 1 \"1 kHz\" 0 \"0\" 0 \"0\" 0>\n").arg(70+dx);
|
||||
s += QString("<GND * 1 %1 360 0 0 0 0>\n").arg(70+dx);
|
||||
for (int i=1; i<=N2ord; i++) {
|
||||
stage = Sections.at(i-1);
|
||||
qDebug()<<stage.N;
|
||||
QString suffix1, suffix2;
|
||||
float C1 = autoscaleCapacitor(stage.C1,suffix1);
|
||||
float C2 = autoscaleCapacitor(stage.C2,suffix2);
|
||||
s += QString("<GND * 1 %1 380 0 0 0 0>\n").arg(200+dx);
|
||||
s += QString("<GND * 1 %1 350 0 0 0 0>\n").arg(360+dx);
|
||||
s += QString("<OpAmp OP%1 1 %2 270 -26 -70 1 0 \"1e6\" 1 \"15 V\" 0>\n").arg(1+(i-1)*Nop1).arg(390+dx);
|
||||
s += QString("<R R%1 1 %2 350 17 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(1+(i-1)*Nr1).arg(200+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 180 17 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(2+(i-1)*Nr1).arg(320+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<C C%1 1 %2 180 15 -26 0 1 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(1+(i-1)*Nc1).arg(200+dx).arg(C1,0,'f',3).arg(suffix1);
|
||||
s += QString("<C C%1 1 %2 250 -26 15 0 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(2+(i-1)*Nc1).arg(150+dx).arg(C2,0,'f',3).arg(suffix2);
|
||||
s += QString("<C C%1 1 %2 250 -26 15 0 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(3+(i-1)*Nc1).arg(250+dx).arg(C1,0,'f',3).arg(suffix1);
|
||||
dx += 510;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
createFirstOrderComponentsHPF(s,Sections.last(),dx+10);
|
||||
}
|
||||
|
||||
s += "</Components>\n";
|
||||
s += "<Wires>\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)==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);
|
||||
}
|
||||
dx += 510;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
createFirstOrderWires(s,dx+10,270);
|
||||
}
|
||||
|
||||
s += "</Wires>\n";
|
||||
}
|
||||
|
||||
void MFBfilter::calcHighPass()
|
||||
{
|
||||
float R1,R2,C1,C2;
|
||||
float Wc = 2*M_PI*Fc;
|
||||
|
||||
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;
|
||||
float C = re*re + im*im;
|
||||
|
||||
qDebug()<<B<<C;
|
||||
|
||||
C1 = 10.0/Fc;
|
||||
C2 = C1/Kv;
|
||||
R1 = B/((2*C1+C2)*Wc);
|
||||
R2 = ((2*C1 + C2)*C)/(B*C1*C2*Wc);
|
||||
|
||||
RC_elements curr_stage;
|
||||
curr_stage.N = k;
|
||||
curr_stage.R1 = 1000*R1;
|
||||
curr_stage.R2 = 1000*R2;
|
||||
curr_stage.R3 = 0;
|
||||
curr_stage.R4 = 0;
|
||||
curr_stage.R5 = 0;
|
||||
curr_stage.C1 = C1;
|
||||
curr_stage.C2 = C2;
|
||||
Sections.append(curr_stage);
|
||||
}
|
||||
|
||||
this->calcFirstOrder();
|
||||
|
||||
}
|
||||
|
||||
void MFBfilter::calcLowPass()
|
||||
{
|
||||
float R1,R2,R3,C1,C2;
|
||||
float Wc = 2*M_PI*Fc;
|
||||
|
||||
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;
|
||||
float C = re*re + im*im;
|
||||
|
||||
qDebug()<<B<<C;
|
||||
|
||||
C2 = (10.0/Fc);
|
||||
C1 = (B*B*C2)/(4*C*(Kv+1));
|
||||
R2 = (2*(Kv+1))/(Wc*(B*C2+sqrt(B*B*C2*C2-4*C*C1*C2*(Kv+1))));
|
||||
R1 = R2/Kv;
|
||||
R3 = 1.0/(C*C1*C2*Wc*Wc*R2);
|
||||
|
||||
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.R5 = 0;
|
||||
curr_stage.C1 = C1;
|
||||
curr_stage.C2 = C2;
|
||||
Sections.append(curr_stage);
|
||||
}
|
||||
|
||||
this->calcFirstOrder();
|
||||
}
|
38
qucs-activefilter/mfbfilter.h
Normal file
@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
mfbfilter.h
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 MFBFILTER_H
|
||||
#define MFBFILTER_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <complex>
|
||||
#include "filter.h"
|
||||
|
||||
class MFBfilter : public Filter
|
||||
{
|
||||
protected:
|
||||
void calcHighPass();
|
||||
void calcLowPass();
|
||||
void createHighPassSchematic(QString &s);
|
||||
void createLowPassSchematic(QString &s);
|
||||
|
||||
public:
|
||||
MFBfilter(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par);
|
||||
|
||||
};
|
||||
|
||||
#endif // MFBFILTER_H
|
50
qucs-activefilter/qf_matrix.h
Normal file
@ -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
|
1580
qucs-activefilter/qf_poly.cpp
Normal file
142
qucs-activefilter/qf_poly.h
Normal file
@ -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 <QtCore>
|
||||
#include <complex>
|
||||
|
||||
#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<float> > &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
|
||||
|
447
qucs-activefilter/qucsactivefilter.cpp
Normal file
@ -0,0 +1,447 @@
|
||||
/***************************************************************************
|
||||
qucsactivefilter.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 "qucsactivefilter.h"
|
||||
#include "sallenkey.h"
|
||||
#include "mfbfilter.h"
|
||||
#include "schcauer.h"
|
||||
#include "transferfuncdialog.h"
|
||||
#include <QTextCodec>
|
||||
|
||||
|
||||
QucsActiveFilter::QucsActiveFilter(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
Nfil = 4;
|
||||
Fc = 1000;
|
||||
ftyp = Filter::NoFilter;
|
||||
|
||||
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
//lblInputData = new QLabel(tr("Входные данные"));
|
||||
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");
|
||||
QDoubleValidator *val1 = new QDoubleValidator(0,100000,3);
|
||||
edtA1->setValidator(val1);
|
||||
edtA2 = new QLineEdit("20");
|
||||
edtA2->setValidator(val1);
|
||||
edtF1 = new QLineEdit("1000");
|
||||
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("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;
|
||||
QStringList lst2;
|
||||
lst2<<tr("Butterworth")
|
||||
<<tr("Chebyshev")
|
||||
<<tr("Inverse Chebyshev")
|
||||
<<tr("Cauer (Elliptic)")
|
||||
<<tr("Bessel")
|
||||
<<tr("User defined");
|
||||
cbxFilterFunc->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("Calculate and copy to clipboard"));
|
||||
connect(btnCalcSchematic,SIGNAL(clicked()),SLOT(slotCalcSchematic()));
|
||||
|
||||
lblResult = new QLabel(tr("Calculation console"));
|
||||
txtResult = new QTextEdit;
|
||||
|
||||
|
||||
lblSch = new QLabel(tr("Filter topology"));
|
||||
lblResp = new QLabel(tr("Filter type:"));
|
||||
cbxResponse = new QComboBox;
|
||||
QStringList lst3;
|
||||
lst3<<tr("LowPass")
|
||||
<<tr("High Pass")
|
||||
<<tr("Band Pass")
|
||||
<<tr("Band Stop");
|
||||
cbxResponse->addItems(lst3);
|
||||
connect(cbxResponse,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateResponse()));
|
||||
connect(cbxResponse,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic()));
|
||||
|
||||
cbxFilterType = new QComboBox;
|
||||
QStringList lst;
|
||||
lst<<tr("Cauer section")
|
||||
<<tr("Multifeedback (MFB)")
|
||||
<<tr("Sallen-Key (S-K)");
|
||||
//<<tr("Пассивный");
|
||||
cbxFilterType->addItems(lst);
|
||||
connect(cbxFilterType,SIGNAL(currentIndexChanged(int)),this,SLOT(slotUpdateSchematic()));
|
||||
this->slotSwitchParameters();
|
||||
|
||||
lblAFR = new QLabel(tr("General amplitude frequency response"));
|
||||
lblTopology = new QLabel(tr("Filter topology preview (one stage)"));
|
||||
|
||||
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();
|
||||
|
||||
s1 = ":/images/cauer.svg";
|
||||
ren = new QSvgRenderer(s1);
|
||||
sz = ren->defaultSize();
|
||||
sz *= 0.65;
|
||||
delete ren;
|
||||
|
||||
sch_pic = new QSvgWidget(s1);
|
||||
sch_pic->setFixedSize(sz);
|
||||
sch_pic->show();
|
||||
|
||||
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(lblRpl1);
|
||||
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);
|
||||
left->addLayout(l3);
|
||||
|
||||
left->addWidget(btnDefineTransferFunc);
|
||||
|
||||
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(lblAFR);
|
||||
right->addWidget(imgAFR);
|
||||
right->addWidget(lblTopology);
|
||||
right->addWidget(sch_pic);
|
||||
right->addStretch();
|
||||
|
||||
top->addLayout(left);
|
||||
top->addLayout(center);
|
||||
top->addLayout(right);
|
||||
|
||||
top1 = new QVBoxLayout;
|
||||
top1->addLayout(top);
|
||||
QSplitter *sp1 = new QSplitter;
|
||||
top1->addWidget(sp1);
|
||||
txtResult->setReadOnly(true);
|
||||
top1->addWidget(txtResult);
|
||||
txtResult->setMinimumHeight(180);
|
||||
|
||||
zenter = new QWidget;
|
||||
this->setCentralWidget(zenter);
|
||||
zenter->setLayout(top1);
|
||||
}
|
||||
|
||||
QucsActiveFilter::~QucsActiveFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void QucsActiveFilter::slotCalcSchematic()
|
||||
{
|
||||
|
||||
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;
|
||||
case 4 : ffunc = Filter::Bessel;
|
||||
par.order = edtOrder->text().toInt();
|
||||
break;
|
||||
case 5 : ffunc = Filter::User;
|
||||
break;
|
||||
default: ffunc = Filter::NoFunc;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
QString s;
|
||||
bool ok = false;
|
||||
|
||||
switch (cbxFilterType->currentIndex()) {
|
||||
case 0 : {
|
||||
if (((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) {
|
||||
SchCauer cauer(ffunc,ftyp,par);
|
||||
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!"));
|
||||
}
|
||||
} else {
|
||||
errorMessage(tr("Unable to use Cauer section for Chebyshev or Butterworth \n"
|
||||
"frequency response. Try to use another topology."));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 1 : {
|
||||
if (!((ffunc==Filter::InvChebyshev)||(ffunc==Filter::Cauer))) {
|
||||
MFBfilter mfb(ffunc,ftyp,par);
|
||||
if (ffunc==Filter::User) {
|
||||
mfb.set_TrFunc(coeffA,coeffB);
|
||||
}
|
||||
ok = mfb.calcFilter();
|
||||
mfb.createPolesZerosList(lst);
|
||||
mfb.createPartList(lst);
|
||||
txtResult->setText(lst.join("\n"));
|
||||
if (ok) {
|
||||
mfb.createSchematic(s);
|
||||
} 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 use MFB filter for Cauer or Inverse Chebyshev \n"
|
||||
"frequency response. Try to use another topology."));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2 : {
|
||||
SallenKey sk(ffunc,ftyp,par);
|
||||
if (ffunc==Filter::User) {
|
||||
sk.set_TrFunc(coeffA,coeffB);
|
||||
}
|
||||
ok = sk.calcFilter();
|
||||
sk.createPolesZerosList(lst);
|
||||
sk.createPartList(lst);
|
||||
txtResult->setText(lst.join("\n"));
|
||||
if (ok) {
|
||||
sk.createSchematic(s);
|
||||
} else {
|
||||
errorMessage(tr("Unable to implement filter with such parameters and topology \n"
|
||||
"Change parapeters and/or topology and try again!"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3 : errorMessage(tr("Function will be implemented in future version"));
|
||||
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 QucsActiveFilter::slotUpdateResponse()
|
||||
{
|
||||
QString s = ":/images/AFR.svg";
|
||||
|
||||
switch (cbxResponse->currentIndex()) {
|
||||
case 0 :
|
||||
s = ":/images/AFR.svg";
|
||||
ftyp = Filter::LowPass;
|
||||
break;
|
||||
case 1 : s = ":/images/high-pass.svg";
|
||||
ftyp = Filter::HighPass;
|
||||
break;
|
||||
case 2 : ftyp = Filter::BandPass;
|
||||
break;
|
||||
case 3 : ftyp = Filter::BandStop;
|
||||
break;
|
||||
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 QucsActiveFilter::slotUpdateSchematic()
|
||||
{
|
||||
slotUpdateResponse();
|
||||
QString s;
|
||||
switch (cbxFilterType->currentIndex()) {
|
||||
case 0 : s = ":images/cauer.svg";
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
QSvgRenderer *ren = new QSvgRenderer(s);
|
||||
QSize sz = ren->defaultSize();
|
||||
sz *= 0.65;
|
||||
delete ren;
|
||||
|
||||
sch_pic->load(s);
|
||||
sch_pic->setFixedSize(sz);
|
||||
}
|
||||
|
||||
void QucsActiveFilter::slotSwitchParameters()
|
||||
{
|
||||
if (cbxFilterFunc->currentIndex()==0) {
|
||||
edtA1->setEnabled(true);
|
||||
edtPassbRpl->setEnabled(false);
|
||||
} else {
|
||||
edtA1->setEnabled(false);
|
||||
edtPassbRpl->setEnabled(true);
|
||||
}
|
||||
|
||||
if ((cbxFilterFunc->currentIndex()==3)||(cbxFilterFunc->currentIndex()==2)) {
|
||||
cbxFilterType->setCurrentIndex(0);
|
||||
cbxFilterType->setDisabled(true);
|
||||
} else {
|
||||
cbxFilterType->setDisabled(false);
|
||||
}
|
||||
|
||||
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);
|
||||
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 QucsActiveFilter::slotDefineTransferFunc()
|
||||
{
|
||||
|
||||
TransferFuncDialog *trfuncdlg = new TransferFuncDialog(coeffA,coeffB,this);
|
||||
if (trfuncdlg->exec()) {
|
||||
trfuncdlg->getCoeffs(coeffA,coeffB);
|
||||
}
|
||||
delete trfuncdlg;
|
||||
}
|
||||
|
||||
void QucsActiveFilter::errorMessage(QString str)
|
||||
{
|
||||
QMessageBox* msg = new QMessageBox(QMessageBox::Critical,tr("Active filter design"),
|
||||
str,
|
||||
QMessageBox::Ok);
|
||||
msg->exec();
|
||||
delete msg;
|
||||
}
|
112
qucs-activefilter/qucsactivefilter.h
Normal file
@ -0,0 +1,112 @@
|
||||
/***************************************************************************
|
||||
qucsactivefilter.h
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 FILTERSINTEZ_H
|
||||
#define FILTERSINTEZ_H
|
||||
|
||||
#include <QtGui>
|
||||
#include <QtSvg>
|
||||
#include <QMainWindow>
|
||||
#include <complex>
|
||||
#include "filter.h"
|
||||
|
||||
class QucsActiveFilter : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QLabel *lblInputData;
|
||||
QLabel *lblA1;
|
||||
QLabel *lblA2;
|
||||
QLabel *lblF1;
|
||||
QLabel *lblF2;
|
||||
QLabel *lblTyp;
|
||||
QLabel *lblKv;
|
||||
QLabel *lblRpl1;
|
||||
QLabel *lblRpl2;
|
||||
QLabel *lblResp;
|
||||
|
||||
QLabel *lblAFR;
|
||||
QLabel *lblTopology;
|
||||
QLabel *lblOrder;
|
||||
|
||||
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;
|
||||
QLineEdit *edtOrder;
|
||||
|
||||
QComboBox *cbxFilterFunc;
|
||||
QPushButton *btnCalcSchematic;
|
||||
QPushButton *btnDefineTransferFunc;
|
||||
|
||||
QLabel *lblResult;
|
||||
QTextEdit *txtResult;
|
||||
|
||||
QSvgWidget *imgAFR;
|
||||
QLabel *lblSch;
|
||||
|
||||
/*QRadioButton *btnLowPass;
|
||||
QRadioButton *btnHighPass;
|
||||
QRadioButton *btnBandPass;
|
||||
QRadioButton *btnBandStop;*/
|
||||
|
||||
QComboBox *cbxFilterType;
|
||||
QComboBox *cbxResponse;
|
||||
|
||||
QPushButton *btnElements;
|
||||
//QPushButton *btnPassive;
|
||||
|
||||
QHBoxLayout *top;
|
||||
QVBoxLayout *left;
|
||||
QVBoxLayout *center;
|
||||
QVBoxLayout *right;
|
||||
QVBoxLayout *top1;
|
||||
|
||||
QSvgWidget *sch_pic;
|
||||
|
||||
QWidget *zenter;
|
||||
|
||||
void errorMessage(QString s);
|
||||
|
||||
QVector< std::complex<float> > Poles;
|
||||
|
||||
float Fc;
|
||||
int Nfil;
|
||||
|
||||
QVector<long double> coeffB;
|
||||
QVector<long double> coeffA;
|
||||
|
||||
Filter::FType ftyp;
|
||||
|
||||
private slots:
|
||||
|
||||
void slotUpdateSchematic();
|
||||
void slotUpdateResponse();
|
||||
void slotCalcSchematic();
|
||||
void slotSwitchParameters();
|
||||
void slotDefineTransferFunc();
|
||||
|
||||
public:
|
||||
QucsActiveFilter(QWidget *parent = 0);
|
||||
~QucsActiveFilter();
|
||||
};
|
||||
|
||||
#endif // FILTERSINTEZ_H
|
12
qucs-activefilter/qucsactivefilter.qrc
Normal file
@ -0,0 +1,12 @@
|
||||
<RCC>
|
||||
<qresource prefix="/images">
|
||||
<file>sk-highpass.svg</file>
|
||||
<file>sk-lowpass.svg</file>
|
||||
<file>mfb-lowpass.svg</file>
|
||||
<file>mfb-highpass.svg</file>
|
||||
<file>AFR.svg</file>
|
||||
<file>cauer.svg</file>
|
||||
<file>high-pass.svg</file>
|
||||
<file>trfunc.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
290
qucs-activefilter/sallenkey.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
/***************************************************************************
|
||||
sallenkey.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "sallenkey.h"
|
||||
#include <iostream>
|
||||
|
||||
SallenKey::SallenKey(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) :
|
||||
Filter(ffunc_, type_, par)
|
||||
{
|
||||
Nr1 = 4;
|
||||
Nc1 = 2;
|
||||
Nop1 = 1;
|
||||
}
|
||||
|
||||
|
||||
void SallenKey::calcLowPass()
|
||||
{
|
||||
float R1,R2,R3,R4,C1,C2;
|
||||
float Wc = 2*M_PI*Fc;
|
||||
float Nst = order/2 + order%2;
|
||||
float Kv1 = pow(Kv,1.0/Nst);
|
||||
qDebug()<<Kv1;
|
||||
|
||||
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;
|
||||
float C = re*re + im*im;
|
||||
|
||||
qDebug()<<B<<C;
|
||||
|
||||
|
||||
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)));
|
||||
R2 = 1/(C*C1*C2*R1*Wc*Wc);
|
||||
|
||||
if (Kv != 1.0) {
|
||||
R3 = Kv1*(R1 + R2)/(Kv1 - 1);
|
||||
R4 = Kv1*(R1 + R2);
|
||||
} else {
|
||||
R3 = 1;
|
||||
R4 = 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 = 1000*R4;
|
||||
curr_stage.R5 = 0;
|
||||
curr_stage.C1 = C1;
|
||||
curr_stage.C2 = C2;
|
||||
Sections.append(curr_stage);
|
||||
}
|
||||
|
||||
this->calcFirstOrder();
|
||||
}
|
||||
|
||||
|
||||
void SallenKey::calcHighPass()
|
||||
{
|
||||
float R1,R2,R3,R4,C1;
|
||||
float Wc = 2*M_PI*Fc;
|
||||
|
||||
float Nst = order/2 + order%2;
|
||||
float Kv1 = pow(Kv,1.0/Nst);
|
||||
|
||||
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;
|
||||
float C = re*re + im*im;
|
||||
|
||||
qDebug()<<B<<C;
|
||||
|
||||
C1 = 10 / Fc;
|
||||
|
||||
R2 = 4*C/(Wc*C1*(B+sqrt(B*B+8*C*(Kv1-1))));
|
||||
|
||||
R1 = C/(Wc*Wc*C1*C1*R2);
|
||||
|
||||
if (Kv != 1.0) {
|
||||
R3 = Kv1*R2/(Kv1 - 1);
|
||||
R4 = Kv1*R2;
|
||||
} else {
|
||||
R3 = 1;
|
||||
R4 = 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 = 1000*R4;
|
||||
curr_stage.R5 = 0;
|
||||
curr_stage.C1 = C1;
|
||||
curr_stage.C2 = C1;
|
||||
Sections.append(curr_stage);
|
||||
}
|
||||
calcFirstOrder();
|
||||
}
|
||||
|
||||
void SallenKey::createHighPassSchematic(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 = order/2; // number of 2-nd order stages
|
||||
int N1stOrd = order%2; // number of 1-st order stages
|
||||
|
||||
s += "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
s += "<Components>\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 += "<Eqn Eqn1 1 270 540 -30 14 0 0 \"K=(out.v/in.v)\" 1 \"yes\" 0>\n";
|
||||
s += QString("<Vac V1 1 %1 260 18 -26 0 1 \"1 V\" 1 \"1 kHz\" 0 \"0\" 0 \"0\" 0>\n").arg(20+dx);
|
||||
s += QString("<GND * 1 %1 290 0 0 0 0>\n").arg(20+dx);
|
||||
for (int i=1; i<=N2ord; i++) {
|
||||
stage = Sections.at(i-1);
|
||||
qDebug()<<stage.N;
|
||||
QString suffix1, suffix2;
|
||||
float C1 = autoscaleCapacitor(stage.C1,suffix1);
|
||||
float C2 = autoscaleCapacitor(stage.C2,suffix2);
|
||||
//qDebug()<<C1<<suffix1<<" "<<C2<<suffix2<<stage.C1<<stage.C2;
|
||||
s += QString("<OpAmp OP%1 1 %2 160 -26 42 0 0 \"1e6\" 1 \"15 V\" 0>\n").arg(stage.N).arg(370+dx);
|
||||
s += QString("<GND * 1 %1 270 0 0 0 0>\n").arg(270+dx);
|
||||
s += QString("<GND * 1 %1 370 0 0 0 0>\n").arg(320+dx);
|
||||
s += QString("<R R%1 1 %2 340 15 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(3+(i-1)*N_R).arg(320+dx).arg(stage.R3,0,'f',3);
|
||||
s += QString("<C C%1 1 %2 190 -26 -45 1 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(2+(i-1)*N_C).arg(200+dx).arg(C2,0,'f',3).arg(suffix2);
|
||||
s += QString("<C C%1 1 %2 190 -26 17 0 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(1+(i-1)*N_C).arg(100+dx).arg(C1,0,'f',3).arg(suffix1);
|
||||
s += QString("<R R%1 1 %2 240 -75 -26 1 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(2+(i-1)*N_R).arg(270+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 70 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(1+(i-1)*N_R).arg(330+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 260 -26 15 1 2 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(4+(i-1)*N_R).arg(410+dx).arg(stage.R4,0,'f',3);
|
||||
dx += 510;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
qDebug()<<Sections.last().N;
|
||||
createFirstOrderComponentsHPF(s,Sections.last(),dx);
|
||||
}
|
||||
|
||||
s += "</Components>\n";
|
||||
s += "<Wires>\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)==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);
|
||||
}
|
||||
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,160);
|
||||
}
|
||||
|
||||
s += "</Wires>\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 = order/2; // number of 2-nd order stages
|
||||
int N1stOrd = order%2; // number of 1-st order stages
|
||||
|
||||
s += "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
s += "<Components>\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 += "<Eqn Eqn1 1 270 540 -30 14 0 0 \"K=(out.v/in.v)\" 1 \"yes\" 0>\n";
|
||||
s += QString("<Vac V1 1 %1 260 18 -26 0 1 \"1 V\" 1 \"1 kHz\" 0 \"0\" 0 \"0\" 0>\n").arg(20+dx);
|
||||
s += QString("<GND * 1 %1 290 0 0 0 0>\n").arg(20+dx);
|
||||
for (int i=1; i<=N2ord; i++) {
|
||||
stage = Sections.at(i-1);
|
||||
qDebug()<<stage.N;
|
||||
QString suffix1, suffix2;
|
||||
float C1 = autoscaleCapacitor(stage.C1,suffix1);
|
||||
float C2 = autoscaleCapacitor(stage.C2,suffix2);
|
||||
s += QString("<OpAmp OP%1 1 %2 160 -26 42 0 0 \"1e6\" 1 \"15 V\" 0>\n").arg(stage.N).arg(370+dx);
|
||||
s += QString("<GND * 1 %1 270 0 0 0 0>\n").arg(270+dx);
|
||||
s += QString("<GND * 1 %1 370 0 0 0 0>\n").arg(320+dx);
|
||||
s += QString("<C C%1 1 %2 70 -26 15 0 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(2+(i-1)*N_C).arg(330+dx).arg(C2,0,'f',3).arg(suffix2);
|
||||
s += QString("<C C%1 1 %2 240 -75 -26 1 1 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(1+(i-1)*N_C).arg(270+dx).arg(C1,0,'f',3).arg(suffix1);
|
||||
s += QString("<R R%1 1 %2 190 -26 -45 1 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(2+(i-1)*N_R).arg(200+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 190 -26 17 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(1+(i-1)*N_R).arg(100+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 340 15 -26 0 1 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(3+(i-1)*N_R).arg(320+dx).arg(stage.R3,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 260 -26 15 1 2 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(4+(i-1)*N_R).arg(410+dx).arg(stage.R4,0,'f',3);
|
||||
dx += 510;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
createFirstOrderComponentsLPF(s,Sections.last(),dx);
|
||||
}
|
||||
|
||||
s += "</Components>\n";
|
||||
s += "<Wires>\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)==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);
|
||||
}
|
||||
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,160);
|
||||
}
|
||||
|
||||
s += "</Wires>\n";
|
||||
}
|
44
qucs-activefilter/sallenkey.h
Normal file
@ -0,0 +1,44 @@
|
||||
/***************************************************************************
|
||||
sallenkey.h
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 SALLENKEY_H
|
||||
#define SALLENKEY_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <complex>
|
||||
#include <math.h>
|
||||
#include "filter.h"
|
||||
|
||||
|
||||
class SallenKey : public Filter
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
void calcHighPass();
|
||||
void calcLowPass();
|
||||
void createHighPassSchematic(QString &s);
|
||||
void createLowPassSchematic(QString &s);
|
||||
|
||||
public:
|
||||
SallenKey(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par);
|
||||
|
||||
//void createSchematic(QString &s);
|
||||
|
||||
};
|
||||
|
||||
#endif // SALLENKEY_H
|
233
qucs-activefilter/schcauer.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/***************************************************************************
|
||||
schcauer.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "schcauer.h"
|
||||
|
||||
SchCauer::SchCauer(Filter::FilterFunc ffunc_, Filter::FType type_, FilterParam par) :
|
||||
Filter(ffunc_, type_, par)
|
||||
{
|
||||
Nr1 = 5;
|
||||
Nop1 = 3;
|
||||
Nc1 = 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()<<Kv1;
|
||||
|
||||
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;
|
||||
float C = re*re + im*im;
|
||||
im = Zeros.at(k-1).imag();
|
||||
float A = im*im;
|
||||
|
||||
qDebug()<<A<<B<<C;
|
||||
|
||||
C1 = 10.0/Fc;
|
||||
C2 = C1;
|
||||
R5 = 1.0/(Wc*C1);
|
||||
R1 = (B*R5)/(Kv1*C);
|
||||
R2 = R5/B;
|
||||
R3 = (B*R5)/C;
|
||||
R4 = (Kv1*C*R5)/A;
|
||||
|
||||
RC_elements curr_sec;
|
||||
curr_sec.N = k;
|
||||
curr_sec.R1 = 1000*R1;
|
||||
curr_sec.R2 = 1000*R2;
|
||||
curr_sec.R3 = 1000*R3;
|
||||
curr_sec.R4 = 1000*R4;
|
||||
curr_sec.R5 = 1000*R5;
|
||||
curr_sec.C1 = C1;
|
||||
curr_sec.C2 = C2;
|
||||
Sections.append(curr_sec);
|
||||
|
||||
}
|
||||
|
||||
this->calcFirstOrder();
|
||||
}
|
||||
|
||||
|
||||
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()<<Kv1;
|
||||
|
||||
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;
|
||||
float C = re*re + im*im;
|
||||
im = Zeros.at(k-1).imag();
|
||||
float A = im*im;
|
||||
|
||||
qDebug()<<A<<B<<C;
|
||||
|
||||
C1 = 10.0/Fc;
|
||||
C2 = C1;
|
||||
R5 = 1.0/(Wc*C1);
|
||||
R1 = (B*A*R5)/(Kv1*C);
|
||||
R2 = (C*R5)/B;
|
||||
R3 = B*R5;
|
||||
R4 = Kv1*R5;
|
||||
|
||||
RC_elements curr_sec;
|
||||
curr_sec.N = k;
|
||||
curr_sec.R1 = 1000*R1;
|
||||
curr_sec.R2 = 1000*R2;
|
||||
curr_sec.R3 = 1000*R3;
|
||||
curr_sec.R4 = 1000*R4;
|
||||
curr_sec.R5 = 1000*R5;
|
||||
curr_sec.C1 = C1;
|
||||
curr_sec.C2 = C2;
|
||||
Sections.append(curr_sec);
|
||||
|
||||
}
|
||||
|
||||
this->calcFirstOrder();
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
int N2ord = order/2; // number of 2-nd order stages
|
||||
int N1stOrd = order%2; // number of 1-st order stages
|
||||
|
||||
s += "<Qucs Schematic ";
|
||||
s += PACKAGE_VERSION;
|
||||
s += ">\n";
|
||||
s += "<Components>\n";
|
||||
s += "<Vac V1 1 80 290 18 -26 0 1 \"1 V\" 0 \"1 kHz\" 0 \"0\" 0 \"0\" 0>\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 += "<Eqn Eqn1 1 640 520 -30 14 0 0 \"K=dB(out.v/in.v)\" 1 \"yes\" 0>\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 += "<GND * 1 80 320 0 0 0 0>\n";
|
||||
|
||||
for (int i=1; i<=N2ord; i++) {
|
||||
stage = Sections.at(i-1);
|
||||
qDebug()<<stage.N;
|
||||
QString suffix1, suffix2;
|
||||
float C1 = autoscaleCapacitor(stage.C1,suffix1);
|
||||
float C2 = autoscaleCapacitor(stage.C2,suffix2);
|
||||
s += QString("<OpAmp OP%1 1 %2 240 -26 -70 1 0 \"1e6\" 1 \"15 V\" 0>\n").arg(1+(i-1)*Nop1).arg(270+dx);
|
||||
s += QString("<OpAmp OP%1 1 %2 400 -26 -70 1 0 \"1e6\" 1 \"15 V\" 0>\n").arg(2+(i-1)*Nop1).arg(300+dx);
|
||||
s += QString("<OpAmp OP%1 1 %2 260 -26 42 0 0 \"1e6\" 1 \"15 V\" 0>\n").arg(3+(i-1)*Nop1).arg(560+dx);
|
||||
s += QString("<C C%1 1 %2 150 -26 17 0 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(1+(i-1)*Nc1).arg(330+dx).arg(C1,0,'f',3).arg(suffix1);
|
||||
s += QString("<C C%1 1 %2 400 -26 17 0 0 \"%3%4\" 1 \"\" 0 \"neutral\" 0>\n").arg(2+(i-1)*Nc1).arg(450+dx).arg(C2,0,'f',3).arg(suffix2);
|
||||
s += QString("<R R%1 1 %2 220 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(1+(i-1)*Nr1).arg(180+dx).arg(stage.R1,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 240 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(2+(i-1)*Nr1).arg(410+dx).arg(stage.R2,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 110 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(3+(i-1)*Nr1).arg(440+dx).arg(stage.R3,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 320 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(4+(i-1)*Nr1).arg(360+dx).arg(stage.R4,0,'f',3);
|
||||
s += QString("<R R%1 1 %2 380 -26 15 0 0 \"%3k\" 1 \"26.85\" 0 \"0.0\" 0 \"0.0\" 0 \"26.85\" 0 \"european\" 0>\n").arg(5+(i-1)*Nr1).arg(190+dx).arg(stage.R5,0,'f',3);
|
||||
s += QString("<GND * 1 %1 290 0 0 0 0>\n").arg(240+dx);
|
||||
s += QString("<GND * 1 %1 440 0 0 0 0>\n").arg(250+dx);
|
||||
|
||||
dx += 580;
|
||||
}
|
||||
|
||||
if (N1stOrd!=0) {
|
||||
if (ftype==Filter::LowPass) {
|
||||
createFirstOrderComponentsLPF(s,Sections.last(),dx+80);
|
||||
} else if (ftype==Filter::HighPass) {
|
||||
createFirstOrderComponentsHPF(s,Sections.last(),dx+80);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s += "</Components>\n";
|
||||
s += "<Wires>\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++) {
|
||||
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+80,260);
|
||||
}
|
||||
|
||||
s += "</Wires>\n";
|
||||
}
|
43
qucs-activefilter/schcauer.h
Normal file
@ -0,0 +1,43 @@
|
||||
/***************************************************************************
|
||||
schcauer.h
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 SCHCAUER_H
|
||||
#define SCHCAUER_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <complex>
|
||||
#include <math.h>
|
||||
#include "filter.h"
|
||||
|
||||
class SchCauer : public Filter // Cauer 2-order section
|
||||
{
|
||||
|
||||
private:
|
||||
void createGenericSchematic(QString &s);
|
||||
|
||||
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
|
1129
qucs-activefilter/sk-highpass.svg
Normal file
After Width: | Height: | Size: 37 KiB |
1129
qucs-activefilter/sk-lowpass.svg
Normal file
After Width: | Height: | Size: 37 KiB |
157
qucs-activefilter/transferfuncdialog.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/***************************************************************************
|
||||
transferfuncdialog.cpp
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 "transferfuncdialog.h"
|
||||
|
||||
TransferFuncDialog::TransferFuncDialog(QVector<long double> &a, QVector<long double> &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]="));
|
||||
|
||||
QStringList indexes;
|
||||
for (int i=0;i<50;i++) {
|
||||
indexes<<QString::number(i);
|
||||
}
|
||||
|
||||
tblA = new QTableWidget;
|
||||
QStringList head1;
|
||||
head1<<tr("a[i]");
|
||||
tblA->setColumnCount(head1.count());
|
||||
tblA->setRowCount(50);
|
||||
tblA->setHorizontalHeaderLabels(head1);
|
||||
tblA->setVerticalHeaderLabels(indexes);
|
||||
tblA->setFixedWidth(150);
|
||||
|
||||
if (!a.isEmpty()) {
|
||||
long double num;
|
||||
int i = a.count()-1;
|
||||
|
||||
foreach (num,a) {
|
||||
QTableWidgetItem *it = new QTableWidgetItem(QString::number((double)num));
|
||||
tblA->setItem(i,0,it);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tblB = new QTableWidget;
|
||||
QStringList head2;
|
||||
head2<<tr("b[i]");
|
||||
tblB->setColumnCount(head2.count());
|
||||
tblB->setRowCount(50);
|
||||
tblB->setHorizontalHeaderLabels(head2);
|
||||
tblB->setVerticalHeaderLabels(indexes);
|
||||
tblB->setFixedWidth(150);
|
||||
|
||||
if (!b.isEmpty()) {
|
||||
long double num;
|
||||
int i = b.count()-1;
|
||||
|
||||
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()));
|
||||
connect(btnAccept,SIGNAL(clicked()),this,SLOT(slotCheckCoeffs()));
|
||||
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->addWidget(imgTrfuncEq);
|
||||
top1->addLayout(top);
|
||||
top1->addLayout(low3);
|
||||
|
||||
|
||||
this->setLayout(top1);
|
||||
|
||||
}
|
||||
|
||||
void TransferFuncDialog::getCoeffs(QVector<long double> &a, QVector<long double> &b)
|
||||
{
|
||||
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;
|
||||
bool ok;
|
||||
long double n = (long double) str.toDouble(&ok);
|
||||
if (ok) a.append(n);
|
||||
}
|
||||
//else if (a0) a.append(0.0);
|
||||
}
|
||||
|
||||
|
||||
//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;
|
||||
|
||||
QString str = itm->text();
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferFuncDialog::slotCheckCoeffs()
|
||||
{
|
||||
|
||||
}
|
58
qucs-activefilter/transferfuncdialog.h
Normal file
@ -0,0 +1,58 @@
|
||||
/***************************************************************************
|
||||
transferfuncdialog.h
|
||||
----------------
|
||||
begin : Wed Apr 10 2014
|
||||
copyright : (C) 2014 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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 TRANSFERFUNCDIALOG_H
|
||||
#define TRANSFERFUNCDIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QtGui>
|
||||
|
||||
class TransferFuncDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QLabel *lblA;
|
||||
QLabel *lblB;
|
||||
QLabel *imgTrfuncEq;
|
||||
QTableWidget *tblA;
|
||||
QTableWidget *tblB;
|
||||
|
||||
QPushButton *btnAccept;
|
||||
QPushButton *btnCancel;
|
||||
|
||||
QHBoxLayout *top;
|
||||
QVBoxLayout *top1;
|
||||
QVBoxLayout *low1;
|
||||
QVBoxLayout *low2;
|
||||
QHBoxLayout *low3;
|
||||
|
||||
public:
|
||||
explicit TransferFuncDialog(QVector<long double> &a, QVector<long double> &b, QWidget *parent = 0);
|
||||
|
||||
void getCoeffs(QVector<long double> &a, QVector<long double> &b);
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
void slotCheckCoeffs();
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // TRANSFERFUNCDIALOG_H
|
BIN
qucs-activefilter/trfunc.png
Normal file
After Width: | Height: | Size: 7.3 KiB |