home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------- *)
- (* SPEKTRUM.PAS *)
- (* Programm zur Aufnahme vom Signalen und zur *)
- (* Berechnung ihres Frequenzspektrums *)
- (* *)
- (* (c) 1991 by Andreas Bartels & toolbox *)
- (* ------------------------------------------------------- *)
- PROGRAM Spektrum;
-
- {$IFDEF CPU87} {$N+} {$ELSE} {$N-} {$ENDIF}
-
- USES
- crt, dos, graph;
-
- Const
- MaxLaenge = 256; (* = 512 SHR ShiftL *)
- dXOben = 250;
- dX = 128; (* X-Achsen-Strichabstand *)
- XStrOben = '[ ms ]';
- XStrUnten = '[ Hz ]';
- YStrOben = '[ V ]';
- YStrUnten = '[/Hz]';
-
- {$IFDEF CPU87}
- TYPE REAL = EXTENDED;
- {$ENDIF}
-
- TYPE
- IntegerFeld = ARRAY[0..MaxLaenge] of INTEGER;
- RealFeld = ARRAY[0..MaxLaenge] of REAL;
-
- VAR
- GraphDriver,
- GraphMode, MaxYWert,
- XLinks, XRechts,
- Y0Oben, Y0Unten,
- Y1Oben, Y1Unten,
- IMR21, IMRA1,
- ShiftL, dXUnten, MYH,
- MaxY, i, j, Hilf : INTEGER;
- Faktor, MaxWert : REAL;
- ch : CHAR;
- HStr : STRING;
- BitRev : IntegerFeld;
- Sinus, Cosinus,
- Wert,
- RealTeil, ImagTeil : RealFeld;
-
-
- FUNCTION Fenster( i, FNr : INTEGER) : REAL;
-
- BEGIN
- CASE
- FNr OF
- 0 : { Rechteck }
- Fenster := 1;
- 1 : { Dreieck }
- Fenster := 1 - 2*abs(i-(maxlaenge SHR 1)) / maxlaenge;
- 2 : { Hanning }
- Fenster := 0.5 - 0.5 * cos(2*Pi*i/maxlaenge);
- 3 : { Hamming }
- Fenster := 0.54 - 0.46 * cos(2*Pi*i/maxlaenge);
- ELSE END;
- END; { Fenster }
-
-
-
-
- PROCEDURE DatenLesen;
-
- var i, k : INTEGER;
- c : REAL;
-
- BEGIN
-
- (* Interrupts sperren *)
- IMR21 := Port[$21];
- IMRA1 := Port[$A1];
- Port[$21]:= $FF;
- Port[$A1]:= $FF;
-
- (* Simulation aus Sinusschwingungen *)
- (* 50 Hz-Sinus *)
- (* FOR i := 0 TO Pred(MaxLaenge) DO
- Wert[i] := 0.4*sin(dXOben*Pi*i/(2.5*Maxlaenge))
- * Fenster(i,0); *)
- (* Verrauschter Sinus *)
- (* c := (63 + random) * 2 * Pi / MaxLaenge;
- FOR i := 0 TO Pred(MaxLaenge) DO
- Wert[i] := ((2*sin(c*i) + Random - Random) / 6)
- * Fenster(i,2); *)
-
- (* 3 Sinusschwingungen überlagert *)
- (* FOR i := 0 TO Pred(MaxLaenge) DO
- Wert[i] := ( 60*Sin(i* 8*2*pi/MaxLaenge)
- +15*Sin(i*24*2*pi/MaxLaenge)
- + 5*Sin(i*40*2*pi/MaxLaenge))
- * Fenster(i,0)/120; *)
-
- (* A/D-Wandler abfragen *)
- FOR i := 0 TO Pred(MaxLaenge) DO BEGIN
- Wert[i] := PORT[$208] * Fenster(i,0);
-
- (* Verzögerung zur Einstellung der Samplefrequenz *)
- FOR k := 0 TO 9 DO;
- END;
-
- (* Alte Interrupts wieder zulassen *)
- Port[$21]:= IMR21;
- Port[$A1]:= IMRA1;
-
- END; { DatenLesen }
-
-
- PROCEDURE LookUpTable;
- (* Erstellt eine Tabelle für Sinus,Cosinus und Bit-Umkehr *)
-
- VAR
- Laenge, L12,
- AdrNorm, AdrBRev : INTEGER;
- WinkelEinheit, Wi : REAL;
-
- BEGIN
-
- (* Sinus und Cosinus *)
- WinkelEinheit := 2*Pi/MaxLaenge;
- L12 := MaxLaenge SHR 1;
- FOR i := 0 TO L12 DO BEGIN
- Wi := WinkelEinheit*i;
-
- (* Symmetrieausnutzung bringt weiteren Zeitgewinn *)
- Sinus[i] := -sin(Wi);
- Sinus[L12-i] := Sinus[i];
- Sinus[L12+i] := -Sinus[i];
- Sinus[MaxLaenge-i] := -Sinus[i];
- Cosinus[i] := cos(Wi);
- Cosinus[L12-i] := -Cosinus[i];
- Cosinus[L12+i] := -Cosinus[i];
- Cosinus[MaxLaenge-i] := Cosinus[i];
- END; { FOR }
-
- (* Bit-Umkehr *)
- AdrBRev := 0;
- BitRev[0] := 0;
- FOR AdrNorm := 1 TO Pred(MaxLaenge) DO BEGIN
- Laenge := MaxLaenge SHR 1;
- WHILE AdrBRev+Laenge > Pred(MaxLaenge) DO
- Laenge := Laenge SHR 1;
- AdrBRev := AdrBRev Mod Laenge + Laenge;
- IF AdrBRev > Pred(AdrNorm) Then BEGIN
- BitRev[AdrNorm] := AdrBRev;
- BitRev[AdrBRev] := AdrNorm;
- END; { IF }
- END; { FOR }
-
- END; { LookUpTable }
-
-
-
- PROCEDURE FFT( RealT : RealFeld );
- (* Sogenannte Hintransformation ! *)
-
- VAR
- TempReal, TempImag,
- WichtungReal, WichtungImag : REAL;
- TabNr, l, m, iSchritt : INTEGER;
-
- BEGIN
-
- FOR i := 0 TO Pred(MaxLaenge) DO BEGIN
- RealTeil[i] := RealT[BitRev[i]];
- ImagTeil[i] := 0;
- END; { FOR }
-
- (* FFT - Algorithmus *)
- l := 1;
- WHILE l < MaxLaenge DO BEGIN
- iSchritt := l SHL 1;
- FOR m := 1 to l DO BEGIN
- TabNr := ROUND(MaxLaenge SHR 1 Div l) * Pred(m);
- WichtungReal := cosinus[TabNr];
- WichtungImag := sinus[TabNr];
- i := Pred(m);
- REPEAT
- j := i+l;
- TempReal := WichtungReal * RealTeil[j]
- - WichtungImag * ImagTeil[j];
- TempImag := WichtungReal * ImagTeil[j]
- + WichtungImag * RealTeil[j];
- RealTeil[j] := RealTeil[i] - TempReal;
- ImagTeil[j] := ImagTeil[i] - TempImag;
- RealTeil[i] := RealTeil[i] + TempReal;
- ImagTeil[i] := ImagTeil[i] + TempImag;
- i := i + iSchritt;
- UNTIL i >= MaxLaenge
- END; { FOR }
- l := iSchritt;
- END; { WHILE }
-
- END; { FFT }
-
-
-
- BEGIN { PROGRAM Spektrum }
-
- XLinks := 50;
- XRechts := 562;
- Y0Oben := 17;
- Y1Oben := 160;
- MaxYWert := Y1Oben - Y0Oben;
- MYH := MaxYWert DIV 2;
- Y0Unten := 182;
- Y1Unten := Y0Unten + MaxYWert;
-
- ShiftL := 0;
- Hilf := MaxLaenge;
- WHILE Hilf < 512 DO BEGIN
- Hilf := Hilf SHL 1;
- INC(ShiftL);
- END;
- dXUnten := (64 SHR ShiftL) * 250 DIV dXOben;
-
- FOR i := 0 TO MaxLaenge DO Wert[i] := 0;
-
- Writeln('Erstelle Look-up-table ... ');
- LookUpTable;
-
- graphdriver := detect;
- (* falls nicht definiert, über "SET BGIPATH=PfadName" setzen *)
- initgraph(graphdriver, graphmode, '');
- RectAngle( 0, 0, 600, 347 );
- OutTextXY( 55, 6, 'S P E K T R U M Ver. 1.03'
- + ' (c) 1991 A. Bartels & toolbox');
-
- (* Beschriftung oben *)
- RectAngle( XLinks, Y0Oben, XRechts, Y1Oben );
- FOR i := 0 TO 4 DO BEGIN
- Line( XLinks+i*dX, Y1Oben, XLinks+i*dX, Y1Oben+5 );
- Str( (i*dXOben):3, HStr );
- OutTextXY( XLinks+i*dX-15, Y1Oben+10, HStr ) ;
- END;
- OutTextXY( XLinks+ROUND(3.5*dX)-15, Y1Oben+10, XStrOben );
- FOR i := -2 TO 2 DO BEGIN
- Line( XLinks-5, Y1Oben-MYH-1-ROUND(i*MaxYWert/5),
- XLinks, Y1Oben-MYH-1-ROUND(i*MaxYWert/5) );
- Str( (i*0.5):4:1, HStr );
- OutTextXY( XLinks-40, Y1Oben-MYH-ROUND((i*MaxYWert/5)+1),
- HStr ) ;
- END;
- OutTextXY( XLinks-45, Y0Oben+ROUND(MaxYWert/6), YStrOben );
-
- (* Beschriftung unten *)
-
- RectAngle( XLinks, Y0Unten, XRechts, Y1Unten );
- FOR i := 0 TO 4 DO BEGIN
- Line( XLinks+i*dX, Y1Unten, XLinks+i*dX, Y1Unten+5 );
- Str( (i*dXUnten):3, HStr );
- OutTextXY( XLinks+i*dX-15, Y1Unten+10, HStr ) ;
- END;
-
- (* 50 Hz - Markierung *)
-
- Line( ROUND(XLinks+(50 SHL Succ(ShiftL) * (dXOben/250))),
- Y1Unten+2,
- ROUND(XLinks+(50 SHL Succ(ShiftL) * (dXOben/250))),
- Y1Unten+7 );
- OutTextXY( XLinks+ROUND(3.5*dX)-15, Y1Unten+10,
- XStrUnten );
- FOR i := 0 TO 5 DO BEGIN
- Line( XLinks-5, Y1Unten-ROUND(i*MaxYWert/5),
- XLinks, Y1Unten-ROUND(i*MaxYWert/5) );
- Str( i:2, HStr );
- OutTextXY( XLinks-40, Y1Unten-ROUND((i*MaxYWert/5)+1),
- HStr ) ;
- END;
- OutTextXY( XLinks-45, Y0Unten+ROUND(MaxYWert/10),
- YStrUnten );
-
- REPEAT
-
- (* Aufnahme und Ausgabe des Signals *)
- DatenLesen;
- MaxWert := 1;
- FOR i := 1 TO MaxLaenge-1 DO
- IF Wert[i] > MaxWert THEN MaxWert := Wert[i];
- SetViewPort( XLinks+1, Y0Oben+1,
- XRechts-1, Y1Oben-1, false );
- ClearViewPort;
- SetViewPort( XLinks, Y0Oben, XRechts, Y1Oben, false );
- Faktor := MaxYWert / MaxWert;
- Line( 0, MYH, 512, MYH );
- MoveTo( 0, MaxYWert-MYH-ROUND(Wert[0]*Faktor) );
- FOR i := 1 TO MaxLaenge DO
- LineTO( i SHL ShiftL,
- MaxYWert-MYH-ROUND(Wert[i]*Faktor) );
-
- (* FFT und Ausgabe des Spektrums *)
- FFT( Wert );
- RealTeil[0] := 0; (* Gleichanteil unterdrücken *)
- ImagTeil[0] := 0;
-
- (* Aus dem komplexen- das Leistungs-Spektrum berechnen *)
-
- FOR i := 1 TO MaxLaenge SHR 1 DO
- Wert[i] := SQRT( SQR(RealTeil[i]) + SQR(ImagTeil[i]) );
- MaxWert := 1;
- FOR i := 1 TO MaxLaenge SHR 1 DO
- IF Wert[i] > MaxWert THEN MaxWert := Wert[i];
- SetViewPort( XLinks+1, Y0Unten+1,
- XRechts-1, Y1Unten-1, false );
- ClearViewPort;
- SetViewPort( XLinks, Y0Unten, XRechts, Y1Unten, false );
- Faktor := MaxYWert / MaxWert;
- MoveTo( 0, MaxYWert - ROUND(Wert[0]*Faktor) );
- FOR i := 1 TO MaxLaenge SHR 1 DO
- LineTO( i SHL (ShiftL+1),
- MaxYWert-ROUND(Wert[i]*Faktor) );
-
- UNTIL KeyPressed;
-
- ch := ReadKey;
- REPEAT UNTIL KeyPressed;
-
- CloseGraph;
-
- END. { Spektrum }
-
- (***********************************************************)
- (* Ende von SPEKTRUM.PAS *)
-