EE1 Filter Design is an active filter design calculator that computes component values for band-pass, low-pass, and high-pass second-order active filters using an operational amplifier topology. For low-pass and high-pass designs, the user selects from four filter approximations — Butterworth, 0.1 dB Chebyshev, 0.5 dB Chebyshev, and 1 dB Chebyshev — with the corresponding pole coefficients stored in arrays T() and H(). Given user-supplied cutoff frequency, voltage gain, and capacitor values, the program solves for resistor values R1 through R4 using standard active filter synthesis equations. The program also includes a frequency-response plotting routine that computes gain in decibels (using the natural log converted to base-10) across 50 points and scales the results to fit the screen using PLOT statements.
Program Analysis
Program Structure
The program is organized as a menu-driven application with distinct sections for each filter type and shared subroutines. Control flow is governed by the variable P$, which holds the menu selection (“1” for band-pass, “2” for low-pass, “3” for high-pass), and is consulted throughout shared subroutines to select the appropriate transfer function branch.
| Line Range | Function |
|---|---|
| 8–32 | Initialization: array allocation, Chebyshev/Butterworth coefficient tables |
| 90–360 | Main menu |
| 400–710 | Band-pass filter design |
| 720–1040 | Low-pass filter design |
| 1100–1210 | Plot menu (frequency vs. W/W0) |
| 1220–1340 | Frequency-domain plot setup |
| 1500–1690 | Subroutine: transfer function evaluation (VV in dB) |
| 2000–2240 | High-pass filter design |
| 2300–2410 | Normalized W/W0 plot |
| 3000–4250 | Graph labeling subroutines |
| 5000–5480 | Logon/splash screen |
| 5500–5510 | Error message: band width must be positive |
| 8000–8230 | Frequency-sweep plot routine |
| 9200–9370 | Filter approximation selection (sets A, B coefficients) |
| 9400–9850 | Plot axis drawing |
| 9900–9961 | Utility subroutines (keypress wait, error clear) |
| 9990–9995 | SAVE and RUN |
Filter Approximation Coefficients
Arrays T() and H() (lines 23–30) store the second-order polynomial coefficients (a and b) for four filter approximations. These correspond to the standard normalized denominator polynomial s² + As + B for each approximation type.
| Index | Type | A (T) | B (H) |
|---|---|---|---|
| 1 | Butterworth | √2 ≈ 1.41421 | 1 |
| 2 | 0.1 dB Chebyshev | 2.37209 | 3.31329 |
| 3 | 0.5 dB Chebyshev | 1.42562 | 1.5162 |
| 4 | 1 dB Chebyshev | 1.09773 | 1.01251 |
Transfer Function Evaluation
The subroutine at line 1500 computes the gain in decibels at a given frequency I. It branches on P$ to apply the correct transfer function for band-pass (lines 1630–1670), low-pass (lines 1570–1590), or high-pass (lines 1530–1560). The complex numerator and denominator are split into real parts X and imaginary parts Y, and the magnitude is converted to dB at line 1680 using the identity 20·log₁₀(|H|) = 20·ln(|H|)/ln(10).
Plot Routine
The plotting routine at line 8000 samples the transfer function at 50 equally spaced frequency points between SF (start frequency) and EF (end frequency), storing results in array G(). It then finds the minimum (Y0) and maximum (Y1) gain values (lines 8080–8130), normalizes the data into array O(), and scales with SCA=29/Y2 to map the dynamic range to 29 pixel columns. PLOT statements at line 8210 draw each point. The W/W0 normalized plot at line 2300 uses a logarithmic frequency sweep: I=10^(L-2)*WC/(2*PI) for L from 1 to 3 in steps of 2/50, covering two decades.
Key BASIC Idioms and Techniques
- The string array
Z$(11,13)acts as a string table for menu labels and separators, avoiding repeated string literals. Y$(1)="ENTER "andY$(2)=" "(spaces) are used to overwrite prompts after input by reprinting the same screen position with blanks — a common screen-editing trick in lieu of line clearing.- The INKEY$ debounce pattern at lines 290–296 and 9280–9310 first waits for a key to be released (
IF INKEY$<>"" THEN GOTO), then waits for a new keypress, preventing auto-repeat artifacts. - FAST/SLOW bracketing (lines 560/675, 2301) is used to accelerate computation-heavy sections while restoring display output for interactive prompts.
- The variable
V$set in the plot menu (line 1175) is later tested throughout the plotting and labeling subroutines to distinguish frequency-axis from W/W0-axis plots.
High-Pass Filter Code Path Anomaly
The high-pass filter section (line 2000) redirects to line 760 (the low-pass input sequence) via GOTO 760 at line 2040, sharing the input routine. After capacitor input at the low-pass line 845, a check IF P$="3" THEN GOTO 2050 is intended to divert to the high-pass computation. However, line 2050 does not exist in the listing; execution would fall through to line 850 (the C1 input for low-pass). This is a bug in the high-pass code path — the high-pass resistor formulas at lines 2090–2140 are unreachable under normal execution.
Screen Coordinate System
The axis-drawing subroutine at line 9400 uses both character-cell PRINT AT positioning and pixel-level PLOT statements. The horizontal axis is drawn as a row of block graphic characters at row 14 (line 9410), while tick marks are placed with PLOT at pixel coordinates. The graph plots data points starting at pixel column 9 (line 8210: PLOT 8+I, ...), with the vertical offset of 14 pixels providing a baseline above the axis line.
Logon Subroutine
The GOSUB at line 8 calls the logon routine at line 5000 before any initialization. This routine allocates a separate DIM O$(2,29) array locally (which shadows the numeric O() array declared later at line 32), displays a company name in both normal and inverse video by iterating character by character, and prints location and copyright text. The character-by-character print loop (lines 5040–5060) prints each character of the string individually at successive column positions, creating an animated reveal effect.
Content
Source Code
8 GOSUB 5000
10 DIM Z$(11,13)
20 DIM Y$(2,6)
21 DIM T(4)
22 DIM H(4)
23 LET T(1)=SQR 2
24 LET T(2)=2.37209
25 LET T(3)=1.42562
26 LET T(4)=1.09773
27 LET H(1)=1
28 LET H(2)=3.31329
29 LET H(3)=1.5162
30 LET H(4)=1.01251
31 DIM G(55)
32 DIM O(55)
90 CLS
100 PRINT AT 4,14;"MENU"
110 PRINT AT 5,14;"''''''''"
120 PRINT AT 7,2;"%S%E%L%E%C%T% %O%P%T%I%O%N%:"
130 LET Z$(1)="BAND PASS"
140 LET Z$(2)="LOW PASS"
150 LET Z$(3)="HIGH PASS"
160 LET Z$(4)="''''''''''''''''''"
170 LET Z$(5)="FREQUENCY"
180 LET Z$(6)="CENTER FREQ."
190 LET Z$(7)="BAND WIDTH"
200 LET Z$(8)="VOLTAGE GAIN"
210 LET Z$(9)="C IN FARADS"
214 LET Z$(10)="C1 IN FARADS"
216 LET Z$(11)=" = ?"
220 LET Y$(1)="ENTER "
230 LET Y$(2)=" "
240 LET A=9
250 FOR I=1 TO 3
260 PRINT AT A,10;INT (I);" = ";Z$(I)
270 LET A=A+2
280 NEXT I
282 PRINT AT A,10;"4 = END"
285 PRINT AT 7,2;"SELECT OPTION:"
290 IF INKEY$<>"" THEN GOTO 300
294 PRINT AT 7,2;"%S%E%L%E%C%T% %O%P%T%I%O%N:"
296 GOTO 285
300 LET P$=INKEY$
310 IF P$="1" THEN GOTO 400
320 IF P$="2" THEN GOTO 720
330 IF P$="3" THEN GOTO 2000
340 IF P$="4" THEN STOP
350 PRINT AT 20,0;"**INVALID ENTRY, TRY AGAIN**"
360 GOTO 290
400 REM ****BAND PASS****
405 CLS
410 PRINT AT 1,11;Z$(1)
420 PRINT AT 2,11;Z$(4)
430 PRINT AT 4,0;Y$(1);Z$(6);Z$(11)
440 INPUT F0
445 PRINT AT 4,0;Y$(2);TAB 22;F0
450 GOSUB 9960
451 IF F0>0 THEN GOTO 460
452 GOSUB 9950
454 GOTO 430
460 PRINT AT 6,0;Y$(1);Z$(7);Z$(11)
470 INPUT BW
471 GOSUB 9960
480 PRINT AT 6,0;Y$(2);TAB 22;BW
482 IF BW>0 THEN GOTO 490
484 GOSUB 5500
486 GOTO 460
490 PRINT AT 8,0;Y$(1);Z$(8);Z$(11)
500 INPUT K
505 GOSUB 9960
510 PRINT AT 8,0;Y$(2);TAB 22;K
512 IF K>=1 THEN GOTO 520
514 PRINT AT 18,0;" **GAIN MUST BE >= ONE**"
516 GOTO 490
520 PRINT AT 10,0;Y$(1);Z$(9);Z$(11)
530 INPUT C1
540 PRINT AT 10,0;Y$(2);TAB 22;C1
560 FAST
580 LET Q=F0/BW
590 LET W0=2*PI*F0
600 LET R1=2*Q/(C1*W0*K)
610 LET R2=2*Q/(C1*W0*(-1+SQR ((K-1)**2+8*Q**2)))
620 LET R3=(1/(C1*C1*W0**2))/(1/R1+1/R2)
630 LET R4=2*R3
640 PRINT AT 12,6;"Q = ";Q;AT 14,6;"R1 = ";R1
650 PRINT AT 16,6;"R2 = ";R2;AT 18,6;"R3 = ";R3
660 PRINT AT 20,6;"R4 = ";R4
670 PRINT AT 21,10;"PLOT (Y/N)?"
675 SLOW
680 IF INKEY$="" THEN GOTO 680
690 IF INKEY$="N" THEN GOTO 90
700 IF INKEY$="Y" THEN GOTO 1100
710 GOTO 680
720 REM **LOW PASS**
725 LET J=2
730 GOSUB 9200
735 CLS
740 PRINT AT 1,11;Z$(2)
750 PRINT AT 2,11;Z$(4)
760 PRINT AT 4,0;Y$(1);Z$(8);Z$(11)
770 INPUT K
775 GOSUB 9960
780 PRINT AT 4,0;Y$(2);TAB 22;K
782 IF K>=1 THEN GOTO 790
784 PRINT AT 18,0;" **GAIN MUST BE >= ONE**"
786 GOTO 760
790 PRINT AT 6,0;Y$(1);"CUTOFF FREQ. ";Z$(11)
800 INPUT FC
801 GOSUB 9960
810 PRINT AT 6,0;Y$(2);TAB 22;FC
812 IF FC>0 THEN GOTO 820
814 GOSUB 9950
816 GOTO 790
820 PRINT AT 8,0;Y$(1);Z$(9);Z$(11)
830 INPUT C
840 PRINT AT 8,0;Y$(2);TAB 22;C
841 PRINT AT 18,0;" "
842 IF C<1E-5/FC THEN GOTO 845
843 PRINT AT 18,0;"**INVALID VALUE OF CAPACITOR C**"
844 GOTO 820
845 IF P$="3" THEN GOTO 2050
850 PRINT AT 10,0;Y$(1);Z$(10);Z$(11)
860 INPUT C1
862 PRINT AT 18,0;" "
865 PRINT AT 10,0;Y$(2);TAB 22;C1
866 IF C1<(A*A+4*B*(K-1))*C/(4*B) THEN GOTO 870
867 PRINT AT 18,0;"*INVALID VALUE OF CAPACITOR C1*"
868 GOTO 850
870 LET AA=(A*A+4*B*(K-1))*C*C
880 LET WC=2*PI*FC
900 LET R1=2/((A*C+SQR (AA-4*B*C*C1))*WC)
910 LET R2=1/(B*C*C1*R1*WC*WC)
920 IF K=1 THEN GOTO 940
930 LET R3=K*(R1+R2)/(K-1)
940 LET R4=K*(R1+R2)
960 PRINT AT 12,4;"R1 = ";R1;AT 14,4;"R2 = ";R2
970 IF K=1 THEN GOTO 985
980 PRINT AT 16,4;"R3 = ";R3;AT 18,4;"R4 = ";R4
982 GOTO 1000
985 PRINT AT 16,4;"R3 = INFINITY";AT 18,4;"R4 = ";R4
1000 PRINT AT 20,10;"PLOT (Y/N)?"
1010 IF INKEY$="" THEN GOTO 1010
1020 IF INKEY$="N" THEN GOTO 90
1030 IF INKEY$="Y" THEN GOTO 1100
1040 GOTO 1010
1100 REM **PLOT LOW PASS**
1105 CLS
1110 PRINT AT 1,14;"PLOT"
1120 PRINT AT 2,14;"''''''''"
1130 PRINT AT 7,2;"SELECT OPTION:"
1140 PRINT AT 9,10;"1 = W/W0"
1150 PRINT AT 11,10;"2 = FREQUENCY"
1160 PRINT AT 7,2;"%S%E%L%E%C%T% %O%P%T%I%O%N:"
1170 IF INKEY$="" THEN GOTO 1200
1175 LET V$=INKEY$
1180 IF INKEY$="1" THEN GOTO 2300
1190 IF INKEY$="2" THEN GOTO 1220
1200 PRINT AT 7,2;"SELECT OPTION:"
1210 GOTO 1160
1220 REM **PLOT FREQ.**
1230 CLS
1240 PRINT AT 7,0;Y$(1);"START FREQUENCY = ?"
1250 INPUT SF
1255 GOSUB 9960
1260 PRINT AT 7,0;Y$(2);TAB 24;SF
1262 IF SF>0 THEN GOTO 1265
1263 GOSUB 9950
1264 GOTO 1240
1265 PRINT AT 18,5;" ";AT 19,0;" "
1270 PRINT AT 9,0;Y$(1);"END FREQUENCY = ?"
1280 INPUT EF
1290 PRINT AT 9,0;Y$(2);TAB 24;EF
1291 IF EF>SF THEN GOTO 1296
1292 PRINT AT 18,5;"**INVALID DATA**"
1293 PRINT AT 19,0;"START FREQ. IS GREATER THAN END FREQ."
1294 GOTO 1240
1296 FAST
1300 CLS
1310 GOSUB 9400
1320 GOSUB 8000
1330 GOTO 1000
1340 GOTO 90
1500 REM **SUB. VV**
1505 LET S=2*PI*I
1510 IF P$="1" THEN GOTO 1630
1520 IF P$="2" THEN GOTO 1570
1530 LET M1=-K*S*S
1540 LET P1=(WC*WC/B)-S*S
1550 LET RR=A*WC*S/B
1560 GOTO 1600
1570 LET M1=K*B*WC*WC
1580 LET P1=(B*WC*WC-S*S)
1590 LET RR=A*WC*S
1600 LET X=M1*P1/(P1*P1+RR*RR)
1610 LET Y=-M1*RR/(P1*P1+RR*RR)
1620 GOTO 1680
1630 LET M1=K*BW*S*2*PI
1640 LET P1=W0*W0-S*S
1650 LET RR=2*PI*BW*S
1660 LET X=M1*RR/(P1*P1+RR*RR)
1670 LET Y=M1*P1/(P1*P1+RR*RR)
1680 LET VV=20*LN (SQR (ABS ((X*X)+ABS (Y*Y))))/LN (10)
1690 RETURN
2000 REM **HIGH PASS**
2004 LET J=3
2005 GOSUB 9200
2010 CLS
2020 PRINT AT 1,11;Z$(3)
2030 PRINT AT 2,11;Z$(4)
2040 GOTO 760
2090 LET WC=2*PI*FC
2100 LET R2=4*B/(C*SQR (A+(A*A+8*B*(K-1)))*WC)
2110 LET R1=B/(C*C*R2*WC*WC)
2120 IF K=1 THEN GOTO 2140
2130 LET R3=K*R2/(K-1)
2140 LET R4=K*R2
2150 PRINT AT 11,4;"R1 = ";R1;AT 13,4;"R2 = ";R2
2160 IF K=1 THEN GOTO 2190
2170 PRINT AT 15,4;"R3 = ";R3;AT 17,4;"R4 = ";R4
2180 GOTO 2200
2190 PRINT AT 15,4;"R3 = INFINITY";AT 17,4;"R4 = ";R4
2200 PRINT AT 20,10;"PLOT (Y/N)?"
2210 IF INKEY$="" THEN GOTO 2210
2220 IF INKEY$="N" THEN GOTO 90
2230 IF INKEY$="Y" THEN GOTO 1100
2240 GOTO 2210
2299 REM **PLOT W0/W**
2300 CLS
2301 FAST
2302 GOSUB 9400
2310 LET II=1
2315 LET IN=2/50
2320 IF P$="1" THEN LET WC=W0
2330 FOR L=1 TO 3 STEP IN
2340 LET I=10**(L-2)*WC/(2*PI)
2350 GOSUB 1500
2360 LET G(II)=VV
2370 LET II=II+1
2380 NEXT L
2390 GOSUB 8080
2400 GOTO 1000
2410 GOTO 90
3000 REM **LABEL FREQ.**
3010 PRINT AT 5,0;"G"
3020 PRINT AT 6,0;"A"
3030 PRINT AT 7,0;"I"
3040 PRINT AT 8,0;"N"
3050 PRINT AT 10,0;"D"
3060 PRINT AT 11,0;"B"
3061 RETURN
3065 GOSUB 3000
3070 PRINT AT 17,10;"FREQUENCY (HZ)"
3080 GOSUB 4000
3090 GOSUB 4100
3100 RETURN
3500 REM **LABEL W0/W**
3510 GOSUB 3000
3520 PRINT AT 17,12;"W/W0"
3530 GOSUB 4000
3540 GOSUB 4100
3550 RETURN
3990 REM
4000 IF P$="1" THEN GOTO 4040
4010 IF P$="2" THEN GOTO 4060
4020 PRINT AT 19,10;"HIGH PASS FILTER"
4030 RETURN
4040 PRINT AT 19,10;"BAND PASS FILTER"
4050 RETURN
4060 PRINT AT 19,10;"LOW PASS FILTER"
4070 RETURN
4090 REM
4100 LET Y5=INT ((Y1-Y0)/3)
4110 LET LL=0
4120 LET Y6=INT (Y1)
4130 FOR L=1 TO 4
4140 PRINT AT LL,1;Y6
4150 LET LL=LL+5
4160 LET Y6=Y6-Y5
4170 NEXT L
4175 IF V$="1" THEN RETURN
4180 LET Y5=INT ((EF-SF)/5)
4190 LET Y6=INT (SF)
4195 LET LL=4
4200 FOR L=1 TO 6
4210 PRINT AT 16,LL;Y6
4220 LET LL=LL+5
4230 LET Y6=Y6+Y5
4240 NEXT L
4250 RETURN
5000 REM **LOGON**
5005 DIM O$(2,29)
5010 LET O$(1)="AMERICAN MICRO PRODUCTS, INC."
5020 LET O$(2)="%A%M%E%R%I%C%A%N% %M%I%C%R%O% %P%R%O%D%U%C%T%S%,% %I%N%C%."
5030 FOR L=1 TO 2
5040 FOR I=1 TO 29
5050 PRINT AT 10,I;O$(L,I)
5060 NEXT I
5450 PRINT AT 16,8;"RICHARDSON, TEXAS"
5460 PRINT AT 20,9;"COPYRIGHT,1982"
5470 NEXT L
5480 RETURN
5500 PRINT AT 18,0;" **BAND WIDTH MUST > ZERO**"
5510 RETURN
8000 REM **PLOT ROUTINE**
8010 LET INC=(EF-SF)/50
8020 LET II=1
8030 FOR I=SF TO EF STEP INC
8040 GOSUB 1500
8050 LET G(II)=VV
8060 LET II=II+1
8070 NEXT I
8080 LET Y1=-1E+38
8090 LET Y0=1E+38
8100 FOR I=1 TO II-1
8110 IF Y0>G(I) THEN LET Y0=G(I)
8120 IF Y1<G(I) THEN LET Y1=G(I)
8130 NEXT I
8140 FOR I=1 TO II-1
8150 LET O(I)=G(I)-Y0
8160 NEXT I
8170 LET Y2=Y1-Y0
8180 LET SCA=29/Y2
8195 SLOW
8196 IF V$="2" THEN GOSUB 3065
8197 IF V$="1" THEN GOSUB 3500
8200 FOR I=1 TO 50
8210 PLOT 8+I,INT (O(I)*SCA)+14
8220 NEXT I
8230 RETURN
9200 CLS
9210 PRINT AT 1,11;Z$(J)
9220 PRINT AT 2,11;Z$(4)
9230 PRINT AT 7,2;"SELECT OPTION:"
9240 PRINT AT 9,10;"1 = BUTTERWORTH"
9250 PRINT AT 11,10;"2 = .1 DB TCHEBYCHEFF"
9260 PRINT AT 13,10;"3 = .5 DB TCHEBYCHEFF"
9270 PRINT AT 15,10;"4 = 1 DB TCHEBYCHEFF"
9280 PRINT AT 7,2;"%S%E%L%E%C%T% %O%P%T%I%O%N:"
9290 IF INKEY$<>"" THEN GOTO 9315
9300 PRINT AT 7,2;"SELECT OPTION:"
9310 GOTO 9280
9315 LET E$=INKEY$
9320 IF E$="1" OR E$="2" OR E$="3" OR E$="4" THEN GOTO 9330
9322 PRINT AT 20,0;"**INVALID ENTRY, TRY AGAIN**"
9324 GOTO 9280
9330 IF E$="1" THEN LET SS=1
9332 IF E$="2" THEN LET SS=2
9334 IF E$="3" THEN LET SS=3
9335 IF E$="4" THEN LET SS=4
9350 LET A=T(SS)
9360 LET B=H(SS)
9370 RETURN
9400 REM **PLOT AXIS**
9410 PRINT AT 14,4;"...................................................."
9420 FOR I=13 TO 43
9430 PLOT 9,I
9440 NEXT I
9450 PLOT 8,24
9460 PLOT 8,34
9470 PLOT 8,43
9475 IF V$="1" THEN GOTO 9720
9480 PLOT 19,13
9490 PLOT 29,13
9500 PLOT 39,13
9510 PLOT 49,13
9520 PLOT 59,13
9710 RETURN
9720 PLOT 17,13
9730 PLOT 21,13
9740 PLOT 29,13
9750 PLOT 34,13
9760 PLOT 42,13
9780 PLOT 46,13
9790 PLOT 51,13
9800 PLOT 54,13
9810 PLOT 57,13
9820 PLOT 59,13
9830 PRINT AT 16,7;".2";TAB 10;".3";TAB 13;".6";TAB 17;"1";TAB 21;"2";TAB 23;"3"
9840 PRINT AT 16,25;"5";TAB 27;"6";TAB 29;"10"
9850 RETURN
9900 PRINT AT 21,2;">>PRESS ANY KEY TO CONTINUE<<"
9910 IF INKEY$="" THEN GOTO 9910
9920 RETURN
9950 PRINT AT 18,0;"*FREQUENCY MUST BE > THAN ZERO*"
9951 RETURN
9960 PRINT AT 18,0;" "
9961 RETURN
9990 SAVE "EE%1"
9995 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

