home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* HIRNSTR.PAS *)
- (* Programm zur Aufnahme und *)
- (* Auswertung von Gehirnwellen *)
- (* (c) 1991 by Andreas Bartels & TOOLBOX *)
- (* ------------------------------------------------------ *)
- {$A-,B-,D-,E+,F+,I-,L-,O-,R-,S-,V-}
- PROGRAM Hirn_Strom_Messung;
-
- {$IFDEF CPU87} {$N+} {$ELSE} {$N-} {$ENDIF}
-
- USES
- Crt, Dos, Graph;
-
- CONST
- MaxLaenge = 128; { = 512 SHR ShiftL }
- dxOben = 250;
- DX = 128; { X-Achsen-Strichabstand }
- XStrOben = '[ ms ]';
- XStrUnten = '[ Hz ]';
- YStrOben = '[ V ]';
- YStrUnten = '[/Hz]';
- { Falls ein Coprozessor vorhanden ist: }
- {$IFDEF CPU87}
- TYPE REAL = EXTENDED;
- {$ENDIF}
-
- TYPE
- IntegerFeld = ARRAY[0..MaxLaenge] OF INTEGER;
- RealFeld = ARRAY[0..MaxLaenge] OF REAL;
- DatenFile = RECORD
- Signal : RealFeld;
- Spektrum : RealFeld;
- Kommentar : STRING;
- END;
-
- 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,
- RealTeil, ImagTeil : RealFeld;
- DatenFileName : STRING[12];
- Dat : DatenFile;
- DatFile : FILE OF DatenFile;
- DateiOK : BOOLEAN;
-
- FUNCTION DatumUndZeitStr : STRING;
- VAR
- Year, Month, Day, WeekDay,
- Hour, Min, Second, Sec100 : WORD;
- Monat, Tag,
- Stunde, Minute, Sekunde : STRING[2];
- Jahr : STRING[4];
- BEGIN
- GetDate(Year, Month, Day, WeekDay);
- Str (Day:1, Tag);
- IF Day < 10 THEN Tag := '0' + Tag;
- Str(Month:1, Monat);
- IF Month < 10 THEN Monat := '0' + Monat;
- Str(Year:1, Jahr);
- Jahr := Copy(Jahr,4,1);
- GetTime(Hour, Min, Second, Sec100);
- Str(Hour:1, Stunde );
- IF Hour < 10 THEN Stunde := '0' + Stunde;
- Str(Min:1, Minute);
- IF Min < 10 THEN Minute := '0' + Minute;
- Str(Second:1, Sekunde);
- IF Second < 10 THEN Sekunde := '0' + Sekunde;
- DatumUndZeitStr := Stunde + Minute + Sekunde +
- Tag + '.' + Monat + Jahr;
- END; { DatumUndZeitStr }
-
- PROCEDURE RahmenUndSoWeiter; { An Grafikkarte anpassen }
- BEGIN
- GraphDriver := Detect;
- InitGraph(GraphDriver, GraphMode, GetEnv('BGIPATH'));
- IF NOT (GraphDriver IN [HercMono, EGA, VGA]) THEN BEGIN
- Writeln('Sorry: Das Programm benötigt eine EGA-, VGA-' +
- ' oder Hercules-Grafikkarte!');
- Halt;
- END;
- IF GraphResult <> GrOK THEN BEGIN
- WriteLn('Grafik konnte nicht initialisiert werden!');
- WriteLn('Geben Sie den Pfad zu den Treibern mit ' +
- 'Hilfe der Umgebungsvariablen "BGIPATH" an!',
- ^G);
- Halt;
- END;
- Rectangle(0, 0, 600, 347);
- OutTextXY( 55, 6, 'H I R N S T R O M Ver. 1.2 ' +
- ' (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 := 0 TO 5 DO BEGIN
- Line(XLinks-5, Y1Oben - 1 - Round(i * MaxYWert / 5),
- XLinks, Y1Oben - 1 - Round(i * MaxYWert / 5));
- Str((i * 0.5):4:1, HStr);
- OutTextXY(XLinks - 40, Y1Oben -
- Round((i * MaxYWert / 5) + 1), HStr);
- END;
- OutTextXY(XLinks-45, Y0Oben + Round(MaxYWert / 8),
- YStrOben);
- Rectangle(XLinks, Y0Unten, XRechts, Y1Unten);
- FOR i := 0 TO 4 DO BEGIN { Beschriftung unten }
- 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);
- END; { RahmenUndSoWeiter }
-
- PROCEDURE Speichern;
- BEGIN
- Sound(50);
- DatenFileName := DatumUndZeitStr;
- Dat.Kommentar := 'Signal und Fourierspektrum.';
- Assign(DatFile, DatumUndZeitStr); ReWrite(DatFile);
- Write(DatFile, Dat); Close(DatFile);
- CH := 'x'; NoSound;
- END; { Speichern }
-
- PROCEDURE Laden;
- VAR HilfStr : STRING[12];
- BEGIN
- ClrScr; GotoXY(10, 6);
- Write('Datum des zu ladenden Signals (tt.mmj) > ');
- ReadLn(DatenFileName);
- GotoXY(10, 7);
- Write('Uhrzeit des zu ladenden Signals (hhmmss) > ');
- ReadLn(HilfStr);
- DatenFileName := HilfStr + DatenFileName;
- {$I-}
- Assign(DatFile, DatenFileName); Reset(DatFile);
- IF (IOResult <> 0) OR (DatenFileName = '') THEN BEGIN
- WriteLn('Datei kann nicht geladen werden!', ^G);
- Delay(1000);
- DateiOK := FALSE;
- Exit;
- END;
- DateiOK := TRUE; Read(DatFile, Dat);
- {$I+}
- Close(DatFile); GotoXY(10, 9);
- WriteLn('Kommentar in ', DatenFileName, ' : ',
- Dat.Kommentar);
- GotoXY(10, 12); Write('Bitte <Return> drücken ');
- ReadLn;
- END; { Laden }
-
- FUNCTION Fenster(i, FNr : INTEGER) : REAL;
- BEGIN
- CASE FNr OF
- 0 : Fenster := 1; { Rechteck }
- 1 : Fenster := 1 - 2 * { Dreieck }
- Abs(i - (MaxLaenge SHR 1)) / MaxLaenge;
- 2 : Fenster := 0.5 - 0.5 * { Hanning }
- Cos(2 * Pi * i / MaxLaenge);
- 3 : Fenster := 0.54 - 0.46 * { Hamming }
- Cos(2 * Pi * i / MaxLaenge);
- END;
- END; { Fenster }
-
- PROCEDURE DatenLesen;
- VAR
- i, k : INTEGER;
- c : REAL;
- BEGIN
- IMR21 := Port[$21]; { Interrupts sperren }
- IMRA1 := Port[$A1];
- Port[$21]:= $FF;
- Port[$A1]:= $FF;
- { A/D-Wandler abfragen }
- i := Port[$208]; { 1. mal Initialisieren }
- Delay(1);
- FOR i := 0 TO MaxLaenge DO BEGIN
- Dat.Signal[i] := Port[$208] * Fenster(i,0);
- { andere Fensterfunktion wird symmetrisch um 127 durch: }
- { Dat.Signal[i] := 127+(PORT[$208]-255) * Fenster(i,3)/2; }
- { Verzögerung zur Einstellung der Samplefrequenz }
- { Justierung einfach nach 50 Hz-Brummen }
- FOR k := 0 TO 3330 DO;
- END;
- Port[$21]:= IMR21; { Alte Interrupts wieder zulassen }
- Port[$A1]:= IMRA1;
- END; { DatenLesen }
-
- PROCEDURE SignalDarstellen;
- BEGIN
- MaxWert := 255; { Nicht auf das Signalmaximum normiert }
- SetViewPort(XLinks + 1, Y0Oben + 1,
- XRechts - 1, Y1Oben - 1, TRUE);
- ClearViewPort;
- SetViewPort(XLinks,Y0Oben,
- XRechts, Y1Oben, TRUE);
- Faktor := MaxYWert / MaxWert;
- MoveTo(0, MaxYWert - Round(Dat.Signal[0] * Faktor));
- FOR i := 1 TO MaxLaenge DO
- LineTo(i SHL ShiftL,
- MaxYWert - Round(Dat.Signal[i] * Faktor));
- END; { SignalDarstellen }
-
- PROCEDURE LookUpTable;
- { Erstellt eine Tabelle für Sinus, Cosinus und Bit-Umkehr }
- VAR
- Laenge, L12,
- AdrNorm, AdrBRev : INTEGER;
- WinkelEinheit, Wi : REAL;
- BEGIN
- WinkelEinheit := 2 * Pi / MaxLaenge; { Sinus und Cosinus }
- L12 := MaxLaenge SHR 1;
- FOR i := 0 TO L12 DO BEGIN
- Wi := WinkelEinheit * i;
- { Symetrieausnutzung 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;
- AdrBRev := 0; BitRev[0] := 0; { Bit-Umkehr }
- 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;
- END;
- END; { LookUpTable }
-
- PROCEDURE FFT( RealT : RealFeld ); { 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;
- l := 1; { FFT - Algorithmus }
- 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;
- l := iSchritt;
- END;
- END; { FFT }
-
- PROCEDURE SpektrumDarstellen;
- BEGIN
- MaxWert := 1;
- Dat.Spektrum[0] := 0;
- FOR i := 0 TO MaxLaenge SHR 1 DO
- IF Dat.Spektrum[i] > MaxWert THEN
- MaxWert := Dat.Spektrum[i];
- SetViewPort(XLinks + 1, Y0Unten + 1,
- XRechts - 1, Y1Unten - 1, FALSE);
- ClearViewPort;
- SetViewPort(XLinks, Y0Unten,
- XRechts, Y1Unten, TRUE);
- Faktor := MaxYWert / MaxWert;
- MoveTo(0, MaxYWert - Round(Dat.Spektrum[0] * Faktor));
- FOR i := 1 TO MaxLaenge SHR 1 DO
- LineTo(i SHL (ShiftL + 1),
- MaxYWert - Round(Dat.Spektrum[i] * Faktor));
- END; { SpektrumDarstellen }
-
- BEGIN { Hauptprogramm }
- { je nach Grafik-Karte anpassen }
- XLinks := 50; XRechts := 562;
- Y0Oben := 17; Y1Oben := 160;
- MaxYWert := Y1Oben - Y0Oben; 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 Dat.Signal[i] := 0;
- WriteLn('Erstelle Look-up-table... ');
- LookUpTable;
- REPEAT
- ClrScr; GotoXY(5, 2);
- Write('***** H I R N S T R O M Ver. 1.2 ' +
- '(c) 1991 A. Bartels & toolbox *****');
- GotoXY(5, 4);
- WriteLn('Befehle : <M>-essen (<S>-peichern, <P>ause)');
- WriteLn(' <L>-aden');
- WriteLn(' <Q>-uit oder <Esc> : Ende ');
- REPEAT
- UNTIL KeyPressed;
- CH:= ReadKey;
- CASE UpCase(CH) OF
- ' ',
- 'M': BEGIN
- RahmenUndSoWeiter;
- REPEAT
- IF KeyPressed THEN
- CH := ReadKey;
- CH := 'x';
- DatenLesen; SignalDarstellen;
- FFT(Dat.Signal);
- Dat.Spektrum[0] := 0;
- FOR i := 1 TO MaxLaenge SHR 1 DO
- Dat.Spektrum[i] := Sqrt(Sqr(RealTeil[i]) +
- Sqr(ImagTeil[i]));
- SpektrumDarstellen;
- { Wartet, ob's gespeichert werden soll }
- Delay(1000);
- IF KeyPressed THEN CH := ReadKey;
- IF CH IN ['S', 's', ' '] THEN Speichern;
- IF CH IN ['P','p'] THEN BEGIN
- REPEAT UNTIL KeyPressed;
- CH := ReadKey;
- END;
- UNTIL CH IN [#27, 'Q', 'q'];
- CH := #0;
- RestoreCrtMode;
- END;
- 'L' : BEGIN
- Laden;
- IF DateiOK THEN BEGIN
- RahmenUndSoWeiter;
- SignalDarstellen;
- SpektrumDarstellen;
- CH := ReadKey;
- RestoreCrtMode;
- CH := #0;
- END;
- END;
- END;
- UNTIL UpCase(CH) IN [#27, 'Q'];
- RestoreCrtMode;
- ClrScr;
- END. { Hirn_Strom_Messung }
- (* ------------------------------------------------------ *)
- (* Ende von HIRNSTR.PAS *)
-