10 REM *** Kaiser Window Program Module *** 20 REM 30 REM This program module will generate the necessary FIR coefficients 40 REM using the Kaiser window sequence. The user can then define the 50 REM output path to either the screen, printer, or an external file 60 REM which can be merged with a FIR program to implement the filter. 70 REM 80 DIM C(256),H(256),FACT(256),WK(256),T(256),CHEX$(256),CARY(256) 90 PI = 3.1415927# 100 CLS 110 REM 120 REM *** Generate filter type menu *** 130 REM 140 LOCATE 4 150 PRINT TAB(11);"*** FIR COEFFICIENT GENERATION USING THE KAISER WINDOW ***" 160 LOCATE 8 170 PRINT TAB(22);"Selections:" 180 PRINT TAB(33);"1....LOWPASS" 190 PRINT TAB(33);"2....HIGHPASS" 200 PRINT TAB(33);"3....BANDPASS" 210 PRINT TAB(33);"4....BANDSTOP" 220 REM 230 PRINT TAB(33);"5....Exit back to Main Menu":PRINT 240 INPUT " Enter desired filter type (number only) --> ",TYPE 250 IF TYPE = 5 THEN LOAD "firprog.bas",R 260 IF TYPE = 1 THEN GOSUB 1290:GOTO 300 'Lowpass prompts routine 270 IF TYPE = 2 THEN GOSUB 1510:GOTO 300 'Highpass prompts routine 280 IF TYPE=3 OR TYPE=4 THEN GOSUB 1730:GOTO 300 'bandpass/stop prompts routine 290 GOTO 100 300 REM 310 REM *** Prompt for general information and output specifications *** 320 REM 330 MES=0 'flag to which error has occured 340 LOCATE 12 350 INPUT " Enter the Sampling Frequency (Fs) in Hz --> ",FSAM 360 IF TYPE=1 THEN FPASS1=0:FSTOP1=0 370 IF TYPE=2 THEN FPASS2=0:FSTOP2=0 380 IF FSAM/2 ",RES$ 470 IF RES$="n" OR RES$="N" THEN 100 480 LOCATE 12 490 PRINT " " 500 REM *** Calculate the Order required *** 510 FCUT2=ABS(FPASS2-FSTOP2) 520 FCUT1=ABS(FPASS1-FSTOP1) 530 IF TYPE=1 THEN DELTAF=FCUT2 540 IF TYPE=2 THEN DELTAF=FCUT1 550 IF TYPE <> 3 AND TYPE <> 4 THEN 570 560 IF FCUT2 < FCUT1 THEN DELTAF = FCUT2 ELSE DELTAF = FCUT1 570 D2=10^(-.05*ATT) 580 D1=(10^(.05*RIP)-1)/(10^(.05*RIP)+1) 590 IF D1 < D2 THEN NUM = D1 ELSE NUM = D2 600 AHP=-20*LOG(NUM)/LOG(10) 610 IF AHP <= 21 THEN D = .9222 ELSE D = (AHP-7.95)/14.36 620 COEFF=INT(2+D*FSAM/DELTAF) 630 IF COEFF/2 = INT(COEFF/2) THEN COEFF=COEFF+1 640 Q=CINT(COEFF-1)/2 650 LOCATE 12 660 PRINT " The calculated # of coefficients required is:";COEFF 670 PRINT 680 PRINT " Enter # of coefficients desired ONLY if greater than";COEFF 690 INPUT " otherwise, press to continue --> ",TEMP 700 IF TEMP = 0 THEN 830 710 IF TEMP < COEFF THEN 750 720 COEFF=TEMP 730 Q=(COEFF-1)/2 740 GOTO 830 750 PRINT 760 FOR BLINK=1 TO 10 770 LOCATE 20 780 PRINT TAB(12);"ERROR! : Order will not satisfy specifications - reenter" 790 FOR DELAY=1 TO 100:NEXT DELAY 800 LOCATE 20:PRINT " " 810 NEXT BLINK 820 GOTO 650 830 CLS 840 LOCATE 12 850 PRINT TAB(28);"Please wait ...working" 860 REM *** Compute Coefficients *** 870 REM 880 IF AHP <= 21 THEN ALP = 0 ELSE ALP = (.1102*(AHP-8.7)) 890 IF AHP > 21 AND AHP <= 50 THEN ALP=.5842*(AHP-21)^.4+.07886*(AHP-21) 900 FACT(1)=1 910 FOR I=2 TO 30 920 FACT[I] = FACT(I-1)*I 930 NEXT I 940 FOR I=0 TO Q 950 BESS=ALP*SQR(1-(2*I/(COEFF-1))^2) 960 IOBES=1:IOALP=1 970 FOR N = 1 TO 30 980 IOBES = IOBES+(((BESS/2)^(N))/FACT(N))^2 990 IOALP = IOALP+(((ALP/2)^(N))/FACT(N))^2 1000 NEXT N 1010 WK(I) = IOBES/IOALP 1020 NEXT I 1030 REM 1040 IF TYPE = 1 THEN GOSUB 2100:GOTO 1080 'calculate coeffs for lowpass 1050 IF TYPE = 2 THEN GOSUB 2210:GOTO 1080 'calculate coeffs for highpass 1060 IF TYPE = 3 THEN GOSUB 2320:GOTO 1080 'calculate coeffs for bandpass 1070 IF TYPE = 4 THEN GOSUB 2430 'calculate coeffs for bandstop 1080 REM 1090 REM *** Rearrange Coefficients *** 1100 FOR I = 0 TO COEFF 1110 C(I)=H(I) ' C'(i) 1120 T(I)=H(I) ' T(i) is temporary storage for H(i)'s 1130 NEXT I 1140 FOR I=0 TO Q 1150 T(I)=H(Q-I) 1160 NEXT I 1170 FOR I=1 TO Q 1180 T(Q+I)=T(Q-I) 1190 NEXT I 1200 FOR I=0 TO COEFF 1210 H(I)=T(I) 1220 NEXT I 1230 REM *** Convert and Output Coefficients *** 1240 REM 1250 GOSUB 4390 'convert coeffs to hex 1260 REM 1270 GOSUB 2760 'call output routine 1280 REM 1290 REM ======================= Lowpass Prompts Routine ======================= 1300 TYPE$="LOWPASS" 1310 CLS 1320 REM 1330 GOSUB 2690 'output filter type 1340 REM 1350 GOSUB 2540 'prompt for AS and AP 1360 REM 1370 LOCATE 12 1380 INPUT " Enter the passband frequency in Hz --> ",FPASS2 1390 LOCATE 12 1400 PRINT " " 1410 LOCATE 5:PRINT TAB(24);"Passband Frequency =";FPASS2;"Hz" 1420 LOCATE 12 1430 INPUT " Enter the stopband frequency in Hz --> ",FSTOP2 1440 IF FSTOP2 <= FPASS2 THEN GOSUB 4540:GOTO 1420 'display error message 1450 LOCATE 12 1460 PRINT " " 1470 LOCATE 6:PRINT TAB(24);"Stopband Frequency =";FSTOP2;"Hz" 1480 RETURN 1490 REM ======================================================================= 1500 REM 1510 REM ====================== Highpass Prompts Routine ======================= 1520 TYPE$="HIGHPASS" 1530 CLS 1540 REM 1550 GOSUB 2710 'output filter type 1560 REM 1570 GOSUB 2540 'prompt for AS and AP 1580 REM 1590 LOCATE 12 1600 INPUT " Enter the passband frequency in Hz --> ",FPASS1 1610 LOCATE 12 1620 PRINT " " 1630 LOCATE 5:PRINT TAB(24);"Passband Frequency =";FPASS1;"Hz" 1640 LOCATE 12 1650 INPUT " Enter the stopband frequency in Hz --> ",FSTOP1 1660 IF FSTOP1 >= FPASS1 THEN GOSUB 4540:GOTO 1640 'display error message 1670 LOCATE 12 1680 PRINT " " 1690 LOCATE 6:PRINT TAB(24);"Stopband Frequency =";FSTOP1;"Hz" 1700 RETURN 1710 REM ======================================================================= 1720 REM 1730 REM =================== Bandpass/stop Prompts routine ===================== 1740 REM 1750 IF TYPE=3 THEN TYPE$="BANDPASS" ELSE TYPE$="BANDSTOP" 1760 CLS 1770 REM 1780 GOSUB 2710 'output filter type 1790 REM 1800 GOSUB 2540 'prompt for AS and AP 1810 REM 1820 LOCATE 12 1830 INPUT " Enter the lower passband frequency in Hz --> ",FPASS1 1840 LOCATE 12 1850 PRINT " " 1860 LOCATE 5:PRINT TAB(24);"Lower Passband Frequency =";FPASS1;"Hz" 1870 LOCATE 12 1880 INPUT " Enter the upper passband frequency in Hz --> ",FPASS2 1890 IF FPASS1 >= FPASS2 THEN GOSUB 4540:GOTO 1870 'display error message 1900 LOCATE 12 1910 PRINT " " 1920 LOCATE 6:PRINT TAB(24);"Upper Passband Frequency =";FPASS2;"Hz" 1930 LOCATE 12 1940 INPUT " Enter the lower stopband frequency in Hz --> ",FSTOP1 1950 IF TYPE=3 THEN IF FSTOP1>=FPASS1 OR FSTOP1>=FPASS2 THEN GOSUB 4540 : GOTO 1930 'display error message 1960 IF TYPE=4 THEN IF FSTOP1<=FPASS1 OR FSTOP1>=FPASS2 THEN GOSUB 4540 : GOTO 1930 'display error message 1970 LOCATE 12 1980 PRINT " " 1990 LOCATE 7:PRINT TAB(24);"Lower Stopband Frequency =";FSTOP1;"Hz" 2000 LOCATE 12 2010 INPUT " Enter the upper stopband frequency in Hz --> ",FSTOP2 2020 IF TYPE=3 THEN IF FSTOP2 <= FPASS2 OR FSTOP2 <= FPASS1 OR FSTOP2 <= FSTOP1 THEN GOSUB 4540:GOTO 2000 'display error message 2030 IF TYPE=4 THEN IF FSTOP2 >= FPASS2 OR FSTOP2 <= FPASS1 OR FSTOP2 <= FSTOP1 THEN GOSUB 4540:GOTO 2000 'display error message 2040 LOCATE 12 2050 PRINT " " 2060 LOCATE 8:PRINT TAB(24);"Upper Stopband Frequency =";FSTOP2;"Hz" 2070 RETURN 2080 REM ======================================================================= 2090 REM 2100 REM ======================= Kaiser Lowpass Routine ======================== 2110 REM 2120 LWCUT=(FPASS2+FSTOP2)/2 2130 H0=2*LWCUT/FSAM 2140 H(0)=H0*WK(0) 'H(0) = C(0)*W(0) 2150 FOR I=1 TO Q 2160 H(I)=H0*((SIN(2*LWCUT*I*PI/FSAM))/(2*LWCUT*I*PI/FSAM))*WK(I) 2170 NEXT I 2180 RETURN 2190 REM ======================================================================= 2200 REM 2210 REM ===================== Kaiser Highpass Routine ========================= 2220 REM 2230 HWCUT=(FPASS1+FSTOP1)/2 2240 H0=-2*HWCUT/FSAM 2250 H(0)=(H0+1)*WK(0) 'H(0) = C(0)*W(0) 2260 FOR I=1 TO Q 2270 H(I)=H0*((SIN(2*HWCUT*I*PI/FSAM))/(2*HWCUT*I*PI/FSAM))*WK(I) 2280 NEXT I 2290 RETURN 2300 REM ======================================================================= 2310 REM 2320 REM ====================== Kaiser Bandpass Routine ======================== 2330 REM 2340 FCUT1=FPASS1-DELTAF/2 2350 FCUT2=FPASS2+DELTAF/2 2360 H(0)=(2/FSAM)*(FCUT2-FCUT1)*WK(0) 2370 FOR I=1 TO Q 2380 H(I)=(1/(I*PI))*(SIN((2*PI*I*FCUT2)/FSAM)-(SIN((2*PI*I*FCUT1)/FSAM)))*WK(I) 2390 NEXT I 2400 RETURN 2410 REM ======================================================================= 2420 REM 2430 REM ====================== Kaiser Bandstop Routine ======================== 2440 REM 2450 FCUT1=FPASS1+DELTAF/2 2460 FCUT2=FPASS2-DELTAF/2 2470 H(0)=((2*(FCUT1-FCUT2)/FSAM)+1)*WK(0) 2480 FOR I=1 TO Q 2490 H(I)=(1/(I*PI))*(SIN((2*PI*I*FCUT1)/FSAM)-(SIN((2*PI*I*FCUT2)/FSAM)))*WK(I) 2500 NEXT I 2510 RETURN 2520 REM ======================================================================= 2530 REM 2540 REM ==================== Prompt for AS and AP Routine ===================== 2550 REM 2560 LOCATE 12 2570 INPUT " Enter the passband ripple in db --> ",RIP 2580 LOCATE 12 2590 PRINT " " 2600 LOCATE 3:PRINT TAB(24);"Passband Ripple (AP) =";RIP;"db" 2610 LOCATE 12 2620 INPUT " Enter the minimum stopband attenuation in db --> ",ATT 2630 LOCATE 12 2640 PRINT " " 2650 LOCATE 4:PRINT TAB(24);"Stopband Attenuation (AS) =";ATT;"db" 2660 RETURN 2670 REM ======================================================================= 2680 REM 2690 REM ======================= Output Specs Header =========================== 2700 LOCATE 1 2710 PRINT " Specifications:" 2720 PRINT TAB(24);TYPE$ 2730 RETURN 2740 REM ======================================================================= 2750 REM 2760 REM ========================== Output Routine ============================= 02770 REM 2780 REM This routine allows the user to define the output 2790 REM path. These include the terminal, line printer, or 2800 REM data file, which includes TMS320 data format for simple 2810 REM merging into a 'blank' filter program. 2820 REM 2830 CLS 2840 LOCATE 8 2850 PRINT " Send coefficients to:" 2860 PRINT TAB(29);"(S)creen" 2870 PRINT TAB(29);"(P)rinter" 2880 PRINT TAB(29);"(F)ile: contains TMS320 (C25 or C31) data format" 2890 PRINT TAB(29);"(R)eturn to Filter Type Menu" 2900 PRINT TAB(29);"(E)xit to DOS" 2910 PRINT 2920 INPUT " Enter desired path --> ",PATH$ 2930 IF PATH$ = "S" OR PATH$ = "s" THEN GOSUB 3000 2940 IF PATH$ = "P" OR PATH$ = "p" THEN GOSUB 3320 2950 IF PATH$ = "F" OR PATH$ = "f" THEN GOSUB 3800 2960 IF PATH$ = "R" OR PATH$ = "r" THEN GOTO 100 2970 IF PATH$ = "E" OR PATH$ = "e" THEN CLS:SYSTEM 2980 GOTO 2830 2990 REM 3000 REM -------------------- Output Coefficients to Terminal ------------------ 3010 REM 3020 CLS 3030 PRINT TAB(15);COEFF;"Coefficient ";TYPE$;" Filter Using the KAISER Window" 3040 PRINT 3050 PRINT " Filter Coefficients:" 3060 PRINT 3070 PRINT TAB(20);"C'(n)";TAB(53);"H(n)" 3080 PRINT TAB(20);"-----";TAB(53);"----" 3090 PRINT 3100 PRINT TAB(51);"DECIMAL";TAB(70);"HEX" 3110 PRINT 3120 FOR I=0 TO Q 3130 IF INT(I/11) <> I/11 OR I = 0 THEN 3190 3140 LOCATE 23:PRINT " Press to view";Q-I+1;"remaining coefficients";:INPUT " ",RESPONSE 3150 LOCATE 23 3160 PRINT " " 3170 GOSUB 4090 'erase coefficients from screen 3180 REM 3190 GOSUB 4190 'convert coeff. index to char, removing spaces in output 3200 PRINT TAB(8); 3210 PRINT "C'(";C1$;")"; 3220 PRINT TAB(15);" = "; 3230 PRINT USING "+#.#####";C(I);:PRINT " = C'(";C2$;")"; 3240 PRINT TAB(41); 3250 PRINT "H(";C1$;")"; 3260 PRINT TAB(47);" = "; 3270 PRINT USING "+#.#####";H(I);: PRINT " = H(";C2$;")"; 3280 PRINT TAB(67);" = ";CHEX$(I) 3290 NEXT I 3300 LOCATE 23:INPUT " Press to return to Output Path Menu ",RET 3310 RETURN 3320 REM --------------------- Output Coefficients to Printer ------------------ 3330 REM 3340 REM This nested routine allows the user to produce hardcopy of the 3350 REM coefficients. NOTE: If this option is specified from the 3360 REM output path menu and the printer is NOT READY, then a 3370 REM "device timeout" will occur via GWBASIC. This will cause 3380 REM exiting to GWBASIC. To restart the FILTER DEVELOPMENT 3390 REM PACKAGE type . This will restart whichever 3400 REM window module selected previously from Main Menu. Program 3410 REM must be re-run to re-develop filter to obtain the hardcopy 3420 REM initially desired. 3430 REM 3440 LPRINT TAB(26);"*** FIR DEVELOPMENT PACKAGE ***" 3450 LPRINT 3460 LPRINT TAB(15);COEFF;"Coefficient ";TYPE$;" Filter Using the KAISER Window" 3470 LPRINT 3480 LPRINT TAB(8);"Passband Ripple (AP) =";RIP;"db" 3490 LPRINT TAB(8);"Stopband Attenuation (AS) =";ATT;"db" 3500 IF TYPE<>1 THEN 3560 3510 LPRINT TAB(8);"Passband frequency =";FPASS2;"Hz" 3520 LPRINT TAB(8);"Stopband frequency =";FSTOP2;"Hz" 3530 IF TYPE<>2 THEN 3560 3540 LPRINT TAB(8);"Passband frequency =";FPASS1;"Hz" 3550 LPRINT TAB(8);"Stopband frequency =";FSTOP1;"Hz" 3560 LPRINT TAB(8);"Lower Passband Frequency =";FPASS1;"Hz" 3570 LPRINT TAB(8);"Upper Passband Frequency =";FPASS2;"Hz" 3580 LPRINT TAB(8);"Lower Stopband Frequency =";FSTOP1;"Hz" 3590 LPRINT TAB(8);"Upper Stopband Frequency =";FSTOP2;"Hz" 3600 LPRINT TAB(8);"Sampling Frequency (Fs) =";FSAM;"Hz" 3610 LPRINT 3620 LPRINT TAB(20);"C'(n)";TAB(53);"H(n)" 3630 LPRINT TAB(20);"-----";TAB(53);"----" 3640 LPRINT 3650 LPRINT TAB(51);"DECIMAL";TAB(70);"HEX" 3660 LPRINT 3670 FOR I=0 TO Q 3680 GOSUB 4190 'convert coeff. index to char, removing spaces in output 3690 LPRINT TAB(8); 3700 LPRINT "C'(";C1$;")"; 3710 LPRINT TAB(15);" = "; 3720 LPRINT USING "+#.#####";C(I);:LPRINT " = C'(";C2$;")"; 3730 LPRINT TAB(41); 3740 LPRINT "H(";C1$;")"; 3750 LPRINT TAB(47);" = "; 3760 LPRINT USING "+#.#####";H(I);:LPRINT " = H(";C2$;")"; 3770 LPRINT TAB(67);" = ";CHEX$(I) 3780 NEXT I 3790 RETURN 3800 REM -------------------- Output Coefficients to File ---------------------- 3810 REM 3820 REM This routine writes the coefficients to a file (named by the 3830 REM user). The file contains TMS320 (C30 or C25) data format. 3840 REM 3850 REM This file can then be merged into a 'blank' filter program 3860 REM via a word processor like PC-WRITE. NOTE: A directory or 3870 REM drive specification can be given along with the filename. 3875 LOCATE 17 3876 PRINT " " 3877 LOCATE 17 3879 INPUT " Enter DSP type (C25 OR C31):";DSP$ 3880 IF DSP$="C31" OR DSP$="c31" THEN GOTO 4030 3885 IF DSP$="C25" OR DSP$="c25" THEN GOTO 3900 3890 GOTO 3875 3900 CLS 3910 LOCATE 12 3920 INPUT " Enter Filename : ",NAM$ 3930 LOCATE 12 3935 PRINT " " 3940 LOCATE 12:PRINT TAB(30);"...saving ";NAM$ 3950 OPEN NAM$ FOR OUTPUT AS 1 3960 FOR I=0 TO COEFF-1 3970 S$=STR$(I) 3980 IF I>9 AND I<100 THEN PRINT#1,"H";RIGHT$(S$,2);" DATA >";CHEX$(I) : GOTO 4010 3990 IF I>99 THEN PRINT#1,"H";RIGHT$(S$,3);" DATA >";CHEX$(I):GOTO 4010 4000 PRINT#1,"H";RIGHT$(S$,1);" DATA >";CHEX$(I) 4010 NEXT I 4020 CLOSE 1 4025 RETURN 4030 CLS 4032 LOCATE 12 4035 INPUT " Enter Filename : ",NAM$ 4038 LOCATE 12 4040 PRINT " " 4042 LOCATE 12:PRINT TAB(30);"...saving ";NAM$ 4045 OPEN NAM$ FOR OUTPUT AS 1 4048 PRINT#1, USING "COEFF .FLOAT +##.######## ;H(###) ==> H(N-1)";H(COEFF-1);COEFF-1 4050 FOR I=COEFF-2 TO 1 STEP -1 4052 PRINT#1, USING " .FLOAT +##.######## ;H(###)";H(I);I 4055 NEXT I 4058 PRINT#1, USING "H0 .FLOAT +##.######## ;H( 0)";H(0) 4060 PRINT#1, "LENGTH .SET (H0-COEFF)+1 ;LENGTH = # OF COEFFs =";COEFF 4062 CLOSE 1 4065 RETURN 4070 REM ======================================================================= 4090 REM ======================== Clear Coefficients =========================== 4100 REM 4110 LOCATE 10 4120 FOR N=1 TO 12 4130 PRINT " " 4140 NEXT N 4150 LOCATE 10 4160 RETURN 4170 REM ======================================================================= 4180 REM 4190 REM ======================= Integer to Character ========================== 4200 REM 4210 REM This routine eliminates the spaces produced in the output 4220 REM when an Integer TYPE is printed. The spaces before and after 4230 REM the integer value are set aside in the event that the integer 4240 REM value is negative. Since the Coefficient index is always 4250 REM non-negative, this value is converter to a character type, 4260 REM and output from this routine as c1$ and c2$. 4270 REM 4280 S1$=STR$(I) 4290 S2$=STR$(COEFF-I-1) 'COEFF-I-1 is the symmetrical alternate of index 4300 C1$=RIGHT$(S1$,1) 4310 C2$=RIGHT$(S2$,1) 4320 IF I > 9 THEN C1$=RIGHT$(S1$,2) 4330 IF I > 99 THEN C1$=RIGHT$(S1$,3) 4340 IF COEFF-I-1 > 9 THEN C2$=RIGHT$(S2$,2) 4350 IF COEFF-I-1 > 99 THEN C2$=RIGHT$(S2$,3) 4360 RETURN 4370 REM ======================================================================= 4380 REM 4390 REM ==================== Convert Coefficients to Hex ====================== 4400 REM 4410 REM This routine converts the coefficients to Hexidecimal 4420 REM via a routine in GWBASIC called HEX$(). The HEX values 4430 REM are accurate to + or - 1. 4440 REM 4450 FOR M=0 TO COEFF-1 4460 CARY(M)=CINT(H(M)*32768!) 'scale by 2^15 4470 IF CARY(M) >= 0 GOTO 4490 4480 CARY(M)=65536!+CARY(M) 4490 CHEX$(M)=HEX$(CARY(M)) 4500 NEXT M 4510 RETURN 4520 REM ======================================================================= 4530 REM 4540 REM ====================== Error Message Routine ========================== 4550 REM 4560 FOR BLINK=1 TO 10 4570 IF MES<>1 THEN 4610 4580 LOCATE 20 4590 PRINT TAB(14);"ERROR : Sampling Frequency (Fs) >= 2*Nyquist - reenter" 4600 GOTO 4630 4610 LOCATE 20 4620 PRINT TAB(15);"ERROR! : Frequency value is inconsistant - reenter" 4630 FOR DELAY=1 TO 100:NEXT DELAY 4640 LOCATE 20 4650 PRINT " " 4660 NEXT BLINK 4670 RETURN 4680 REM =======================================================================