use same convention for directory name

* Use `qucs-[name of tool]` for directory
This commit is contained in:
Guilherme Brondani Torri 2014-07-15 20:41:50 +02:00
parent 99ed320c03
commit 8fd9ce6c94
35 changed files with 11167 additions and 2 deletions

View File

@ -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 \

View File

@ -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
View 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
View 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

View 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
View File

@ -0,0 +1,2 @@
QucsActiveFilter is tool for sintezing active and passive analog filters.

View 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");

View 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

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 52 KiB

View 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
View 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

View 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

View 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();
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 35 KiB

View 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();
}

View 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

View 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

File diff suppressed because it is too large Load Diff

142
qucs-activefilter/qf_poly.h Normal file
View 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

View 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;
}

View 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

View 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>

View 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";
}

View 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

View 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";
}

View 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

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 37 KiB

View 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()
{
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB