IRQ-Routine (SB, TP)

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Antworten
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

IRQ-Routine (SB, TP)

Beitrag von wobo »

Kennt sich einer von Euch etwas genauer mit dem IRQ-Acknowledgement (Port[$20] := $20) aus? Meines Wissens, muß dieses am Ende einer Hardware-Interrupt-Service-Routine ausgegeben werden, damit der IRQ-Controller weiß, dass er den nächsten IRQ für eben diesen IRQ auslösen darf, oder?

z.B. für einen Tastaturhandler (IRQ2=Int9);

Code: Alles auswählen

PROCEDURE TastaturInt; interrupt;  
BEGIN
     inkey := Port[$60];
     { .... }
     Port[$20] := $20;
END;

Das IRQ-Acknowledgement ist hier am Ende der Interrupt-Service-Routine angeordnet, was ich nachvollziehen kann. Es soll ja - wenn ich das richtig verstanden habe - dem IRQ-Controller sagen: „Ich bin fertig, Du darfst jetzt einen neuen Int-9 auslösen.“


Ganz anders meine Soundblaster-Beispiel-Routinen. Diese lösen das iRQ-Acknowledgement am Anfang der Interrupt-Service-Routine aus, wie es meines Wissens auch Creative verlangt.


Meine SB-Interrupt-Routine (f. SB IRQ5 u. IRQ7) sieht daher z.B. so aus:

Code: Alles auswählen

PROCEDURE SB_Int; interrupt;
VAR b : byte;
BEGIN
     b := Port[$22E];                                           {1}
     Port[$20] := $20;                                         {2}
     Vermix_ganz_zeitaufwendig_meine_Samples;    {3}
END;  


{1} sagt der SB (Basis=$220), dass der gemeldete IRQ angenommen wurde,
{2} IRQ-Acknowledgement, welches nach Creative direkt nach der SB-Entlastung ausgegeben werden muss,
{3} meine sehr zeitaufwendige Sound-Vermixungsroutine.

So wie ich das jetzt verstanden habe, könnte also die Situation auftreten, dass mein PC zu langsam ist, und ein erneuter SB-IRQ aufgerufen wird, obwohl mein alter ja noch gar nicht abgearbeitet ist. Denn ich habe ja sehr frühzeitig das IRQ-Acknowledgement gegeben.

Ich dachte daher, dass ich zwei globale Variablen benutze, die mir als Flag sagen, ob mein PC zu langsam ist, nämlich

CalculatingSamples : boolean = false;
CPUtooslow : boolean = false;

Meine SB-IRQ-Routine sähe dann so aus:

Code: Alles auswählen

PROCEDURE SB_Int; interrupt;
VAR b : byte;
BEGIN
     b := Port[$22E];                                                 {1}
     Port[$20] := $20;                                               {2}
     If CalculatingSamples then CPUtooslow := true;
     CalculatingSamples := true;
     if Not CPUtooSlow then
        Vermix_ganz_zeitaufwendig_meine_Samples; {3}
     CalculatingSamples := false;
END;    
Ich frage dann in meinem Hauptprogramm laufend ab, ob das Flag CPUtooslow gesetzt ist und beende dann ggf. das Hauptprogramm mit dem Hinweis, dass der PC (jedenfalls für die gewählte SB-Frequenz) zu langsam ist.

Jetzt habe ich genau diese Situation: mein PC (386sx16) vermixt bei 12 kHz die Samples tadellos, bei 16 kHz ist er aber schon zu langsam. Mein Rechner steht dann: es wird ausschließlich (total verzerrter) Sound ausgegeben. Mein Hauptprogramm hat irgendwie keine Chance, das Flag CPUtooslow abzufragen und wie gewünscht zu beenden. Auch Ctrl-Break etc. hilft nichts mehr. Auf NumLock oder andere Tasten reagiert das BIOS nicht mehr. Es hilft nur noch ein Reset, um dem Graus ein Ende zu setzen.


Irgendwie wird in der SB-IRQ-Routine auch mein Flag CPUtooslow nicht gesetzt. Denn würde es gesetzt, dürften ja überhaupt keine Samples mehr vermixt werden. Dies ist aber definitiv nicht der Fall: Das Vermixen geht einfach weiter, nur eben zu langsam.

Weiss jemand Rat? Oder – etwas verallgemeinert – kennt jemand eine Methode, wie per Software überprüft werden kann, ob eine CPU noch schnell genug ist, immer wieder hintereinander auftretende Hardware-IRQs abzuarbeiten?
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: IRQ-Routine (SB, TP)

Beitrag von freecrac »

Hallo wobo, vorweg muss ich hierbei darauf hinweisen das ich noch nie auf einem PC Sound programmiert habe. Meine letzten Versuche ein paar Töne zu programmieren war auf dem C64er.
Aber ich habe hier "Das Soundblaster Buch" von Josha Munnik/Eric Oostendorp vom Sybex-Verlag vor mir liegen.
wobo hat geschrieben:Kennt sich einer von Euch etwas genauer mit dem IRQ-Acknowledgement (Port[$20] := $20) aus? Meines Wissens, muß dieses am Ende einer Hardware-Interrupt-Service-Routine ausgegeben werden, damit der IRQ-Controller weiß, dass er den nächsten IRQ für eben diesen IRQ auslösen darf, oder?

z.B. für einen Tastaturhandler (IRQ2=Int9);

Code: Alles auswählen

PROCEDURE TastaturInt; interrupt;  
BEGIN
     inkey := Port[$60];
     { .... }
     Port[$20] := $20;
END;
Das IRQ-Acknowledgement ist hier am Ende der Interrupt-Service-Routine angeordnet, was ich nachvollziehen kann. Es soll ja - wenn ich das richtig verstanden habe - dem IRQ-Controller sagen: „Ich bin fertig, Du darfst jetzt einen neuen Int-9 auslösen.“
Ja genau, so kenne ich es auch.
Ganz anders meine Soundblaster-Beispiel-Routinen. Diese lösen das iRQ-Acknowledgement am Anfang der Interrupt-Service-Routine aus, wie es meines Wissens auch Creative verlangt.

Meine SB-Interrupt-Routine (f. SB IRQ5 u. IRQ7) sieht daher z.B. so aus:

Code: Alles auswählen

PROCEDURE SB_Int; interrupt;
VAR b : byte;
BEGIN
     b := Port[$22E];                                           {1}
     Port[$20] := $20;                                         {2}
     Vermix_ganz_zeitaufwendig_meine_Samples;    {3}
END;  


{1} sagt der SB (Basis=$220), dass der gemeldete IRQ angenommen wurde,
{2} IRQ-Acknowledgement, welches nach Creative direkt nach der SB-Entlastung ausgegeben werden muss,
{3} meine sehr zeitaufwendige Sound-Vermixungsroutine.
Eigentlich darf so eine IRQ-Routine nicht sehr lang sein. Das bedeutet das man dort nur wenige Dinge machen kann, aber keine zeitaufwendige Sound-Vermixungsroutine.
Diese lagert man am besten ins Hauptprogramm aus. Mit der IRQ-Routine und dafür spezifizierte Speicheradressen (die man als Flags verwendet kann) steuert man dann ob die Vermixungsroutine etwas tun soll, oder nicht.

In einem Beispielprogramm zur Interruptsteuerung aus dem Buch(Kapitel über DSP Programmieren) wird hier eine Speicher-Adresse verwendet wo die Samplelänge eingestellt wird.
Auch wird innerhalb der IRQ-Routine ein Befehle via Port an die SB übertragen. In dieser Unter-Routine wird dieses 200 mal versucht und dabei geschaut, ob es erfolgreich war (mit "in al, dx" und "or al, al" Prüfe Bit 7)
und wenn das Übertragen geklappt hat, dann wird der eigentliche Befehlswert zur SB übertragen.

Zum Schluss wird erst EOI gesendet, die gepushten Register vom Stack gepoppt und mit "iret" beendet.
So wie ich das jetzt verstanden habe, könnte also die Situation auftreten, dass mein PC zu langsam ist, und ein erneuter SB-IRQ aufgerufen wird, obwohl mein alter ja noch gar nicht abgearbeitet ist. Denn ich habe ja sehr frühzeitig das IRQ-Acknowledgement gegeben.

Ich dachte daher, dass ich zwei globale Variablen benutze, die mir als Flag sagen, ob mein PC zu langsam ist, nämlich

CalculatingSamples : boolean = false;
CPUtooslow : boolean = false;

Meine SB-IRQ-Routine sähe dann so aus:

Code: Alles auswählen

PROCEDURE SB_Int; interrupt;
VAR b : byte;
BEGIN
     b := Port[$22E];                                                 {1}
     Port[$20] := $20;                                               {2}
     If CalculatingSamples then CPUtooslow := true;
     CalculatingSamples := true;
     if Not CPUtooSlow then
        Vermix_ganz_zeitaufwendig_meine_Samples; {3}
     CalculatingSamples := false;
END;    
Ich frage dann in meinem Hauptprogramm laufend ab, ob das Flag CPUtooslow gesetzt ist und beende dann ggf. das Hauptprogramm mit dem Hinweis, dass der PC (jedenfalls für die gewählte SB-Frequenz) zu langsam ist.

Jetzt habe ich genau diese Situation: mein PC (386sx16) vermixt bei 12 kHz die Samples tadellos, bei 16 kHz ist er aber schon zu langsam. Mein Rechner steht dann: es wird ausschließlich (total verzerrter) Sound ausgegeben. Mein Hauptprogramm hat irgendwie keine Chance, das Flag CPUtooslow abzufragen und wie gewünscht zu beenden. Auch Ctrl-Break etc. hilft nichts mehr. Auf NumLock oder andere Tasten reagiert das BIOS nicht mehr. Es hilft nur noch ein Reset, um dem Graus ein Ende zu setzen.


Irgendwie wird in der SB-IRQ-Routine auch mein Flag CPUtooslow nicht gesetzt. Denn würde es gesetzt, dürften ja überhaupt keine Samples mehr vermixt werden. Dies ist aber definitiv nicht der Fall: Das Vermixen geht einfach weiter, nur eben zu langsam.

Weiss jemand Rat? Oder – etwas verallgemeinert – kennt jemand eine Methode, wie per Software überprüft werden kann, ob eine CPU noch schnell genug ist, immer wieder hintereinander auftretende Hardware-IRQs abzuarbeiten?
Wie gesagt, ich würde auf keinen PC, egal wie schnell er ist, eine IRQ-Routine mit zu vielen Befehlen bestücken, sondern nur dafür verwenden um z.B. Flags zu setzen, die dann von der Hauptroutine ausgewertet werden, um eine zeitaufwendige Routine im Hauptprogramm anzustossen, bzw. zu beenden.

....

Um die Geschwindigkeitunterschiede von verschieden schnellen CPUs zu ermitteln habe ich eine Testschleife mit 64 NOPs verwendet, wo ein Zähler die jeweiligen Runden zählt. Die Testschleife läuft genau eine Sekunde lang und je noch CPU-Geschwindigkeit wird die Schleife mehr oder minder oft ausgeführt und dabei ein Zähler hochgezählt. Damit konnte ich die Geschwindigkeit eines von mir verwendeten Menüs, welches man über Cursortasten bedient, mit einer entsprechenden Verzögerungsschleife steuern, wobei der ermittelte Zähler hierbei mit eingerechnet wird und für eine jeweils angepasste Geschwindigkeit sorgt. Anders war das Menü auf schnelleren CPUs nicht zu bedienen, da sonst alle Menüpunkte zu schnell durchlaufen wurden und es dann eher zufällig war an welchem Menüpunkt angehalten wurde, auch wenn man die Taste nur ganz kurz drückt.

In der nun folgenden Routine wird zunächst überprüft ob nur ein 286er, oder bereits ein 386er+ vorhanden ist und dann zu einer von zwei Schleifen gesprungen. Die eine Schleife verwendet nur zwei 16Bit-Register, die andere Schleife ein 32Bit-Register als Zähler.
Am Ende wird eine Datei(SPEED.tic) mit 4 Bytes angelegt mit dem Inhalt des Schleifenzählers. Diese Datei kann dann von anderen Anwendungen eingeladen werden.

Code: Alles auswählen

.MODEL SMALL
.386P
.387
.CODE
 org 100h
                Cpu86    =   0        ; Wert als Index in der Takt-Tabelle
                Cpu286   =   4
                Cpu386   =   8
                Cpu486   =  12
                Cpu586   =  16

START:    mov      ax, @DATA
          mov      ds, ax             ; DS auf Daten-Bereich
;-------------------------------------
          call GETCPU                 ; Prozessor-Analyse:    AX=CPU
;-------------------------------------
          call GETSPEED               ; Zählschleife
;-------------------------------------
          call FILE                   ; create a new file
;-------------------------------------
          mov      ah, 4Ch            ; Dos-Rücksprung, Programm-Ende
          int    21h
;────────────────────────────────────────────────────────────────────────────
;                         U N T E R - R O U T I N E N
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
GETCPU:   mov      ax, Cpu86
          xor      bx, bx
          push     bx                 ; Null auf Stack
          popf                        ; Null in Flagregister
          pushf
          pop      bx                 ; zurück nach bx
          and      bh, 0F0h
          cmp      bh, 0F0h           ; wenn gleich, dann 8086
          je  short CPUOK
;-------------------------------------
          mov      ax, Cpu286
          push     7000h              ; dasselbe mit 7000h
          popf
          pushf
          pop      bx
          and      bh, 70h
          jz  short CPUOK
;-------------------------------------
          mov      ax, Cpu386
          mov      edx, esp
          and      esp, 0FFFCh        ; durch vier teilbare Adr.
          pushfd
          pop      ebx
          mov      ecx, ebx
          btc      ebx, 18            ; Bit 18 umdrehen
          push     ebx
          popfd
          pushfd
          pop      ebx
          push     ecx                ; alte Flaggen zurück
          popfd
          mov      esp, edx           ; Stack zurück
          cmp      ecx, ebx           ; wenn gleich dann 386
          jz  short CPUOK
;-------------------------------------
          mov      ax, Cpu486
          btc      ecx, 21
          push     ecx
          popfd
          pushfd
          pop      ebx
          cmp      ebx, ecx           ; wenn ungleich, dann 486
          jnz short CPUOK
;-------------------------------------
          mov      ax, Cpu586         ; sonst Pentium
;----------------------------------------------------------------------------
CPUOK:    mov      bp, ax
          ret                         ; AX=Cpu
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
GETSPEED: cli                         ; Interrupt's verbieten
          xor      ax, ax
          mov      es, ax             ; ES auf Seg.: 0
;-------------------------------------
          mov      di, es:[20h]       ; Vector von INT 8 retten (Offset)
          mov      si, es:[22h]       ;                         (Segment)
;-------------------------------------
          mov      es:[20h], OFFSET NEUVEC ; Interrupt-Vector von INT 8
          mov      es:[22h], cs            ; auf neue Routine legen
;-------------------------------------
          mov      al, 36h            ; RUNDE auf 18,2 Hertz (Standart)
          out      43h, al
          xor      al, al
          out      40h, al            ; low
          out      40h, al            ; high
;-------------------------------------
          cmp      bp, 8              ;  32-Bit-CPU ?
          jb  short M16
          jmp  M32
;---------------------------------------------------------------------------
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
M16:      mov      bp, 1              ; Aktiv-Flag = IRQ-Ende wenn 0
          xor      cx, cx             ; Zähler low
          xor      dx, dx             ; Zähler high
          sti                         ; neuen Interrupt 8 starten
;-------------------------------------
S1:       and      bp, bp             ; Auf IRQ-Ende warten
          jnz S1
          mov      bp, 1              ; Für's Zählen IRQ Aktiv-Flag setzen
;-------------------------------------
S2:       inc      cx                 ; Hauptzählschleife
          jnz short S3
          inc      dx
;-------------------------------------
S3:       nop                         ; 64 Nop's
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
;-------------------------------------
          and      bp, bp             ; auf Timer-IRQ-Ende abfragen
          jnz S2                      ; weiter, wenn Timer-IRQ noch aktiv
;-------------------------------
          mov      RUNDE, cx          ; Zähler low retten
          mov      RUNDE+2, dx        ; Zähler high retten
;---------------------------------------------------------------------------
ANALYS:   cli                         ; Interrupts verbieten
          mov      es:[20h], di       ; alten Interrupt-Vector
          mov      es:[22h], si       ; von INT 8 wiederherstellen
          sti                         ; Interrupts erlauben
          ret
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
M32:      mov      bp, 1              ; Aktiv-Flag = IRQ-Ende wenn 0
          xor      ecx, ecx           ; Zähler
          sti                         ; neuen Interrupt 8 starten
;-------------------------------------
S4:       and      bp, bp             ; Auf IRQ-Ende warten
          jnz S4
;-------------------------------------
          mov      bp, 1              ; Für's Zählen IRQ Aktiv-Flag setzen
;-------------------------------------
S5:       inc      ecx                ; Hauptzählschleife
          nop                         ; 64 Nop's
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop
          nop

          nop
          nop
          nop
          nop
;-------------------------------------
          and      bp, bp             ; auf Timer-IRQ-Ende abfragen
          jnz S5                      ; weiter, wenn Timer-IRQ noch aktiv
;---------------------------------------------------------------------------
          mov     DWORD PTR[RUNDE], ecx ; Zähler retten
          jmp  ANALYS
;────────────────────────────────────────────────────────────────────────────
;               neue   I R Q - R o u t i n e   für  INT 8
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
NEUVEC:   mov      al, 20h            ; neue IRQ-Routine für INT 8
          dec      bp                 ; Aktiv-Flag löschen
          out      20h, al            ; =EOI
          iret
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16) + 16
;---------------------------------------------------------------------------
FILE:     mov      dx, OFFSET SPEEDNAM
          xor      cx, cx
          mov      ah, 3Ch              ; Datei erstellen
          int    21h
          mov      bx, ax
;---------------------------------------
          mov      dx, OFFSET RUNDE
          mov      cx, 4
          mov      ah, 40h              ; Datei beschreiben
          int    21h
;---------------------------------------
          mov      ah, 3Eh              ; Datei schließen
          int    21h
          ret
;────────────────────────────────────────────────────────────────────────────
;                          D A T E N - B E R E I C H
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/64)*64) + 64
;---------------------------------------------------------------------------
.DATA
 org 0
;---------------------------------------------------------------------------
RUNDE    DW 0, 0                        ; Anzahl der Schleifen-Durchläufe
SPEEDNAM DB "SPEED.tic", 0
;────────────────────────────────────────────────────────────────────────────
.STACK 20h
 end
Meine Anwendung mit den Menü habe ich auf einem 386er mit 40 Mhz programmiert. Nun habe ich diese Anwendung unter XP mit DOSBox 0.74 erneut auf meinem Core2Quad mit 2700 Mhz getestet und das Menü kann man immer noch bedienen.
Die Anzahl der Schleifendurchläufe(im Speed.tic) ist dort Hex: 78E536. Für die Cursortasten rechts/links multipliziere ich diesen Wert mit "Hori_Speed = 32h" und für die Cursortasten oben/unten multipliziere ich den Wert mit "Vert_Speed = 24h", um daraus eine Verzögerungsschleife für die Menübedienung zu berechnen.

Dirk
tom4DOS
BIOS-Flasher
Beiträge: 390
Registriert: Do 24. Feb 2011, 17:20
Wohnort: München

Re: IRQ-Routine (SB, TP)

Beitrag von tom4DOS »

Ich weiß nicht, ob es Dir weiterhilft aber Du kannst Dir mal folgende Pascal-Unit anschauen:
http://homepages.cae.wisc.edu/~brodskye/smix/smix.html
Die macht wohl genau das, was Du zu programmieren versuchst; evtl. kannst Du da etwas "spicken". Ich bin zwar nicht gerade ein Pascal-Programmierer, schon gar nicht bei Soundkarten, aber der Autor von SMIX ruft in seiner Interrupt-Handler-Funktion auch erst die Mixing-Routine auf und sendet zum Schluß das INT-ACK.

Gruß, Thomas
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: IRQ-Routine (SB, TP)

Beitrag von wobo »

freecrac hat geschrieben: ...
Aber ich habe hier "Das Soundblaster Buch" von Josha Munnik/Eric Oostendorp vom Sybex-Verlag vor mir liegen.
Das habe ich auch!
freecrac hat geschrieben: ...
Eigentlich darf so eine IRQ-Routine nicht sehr lang sein. Das bedeutet das man dort nur wenige Dinge machen kann, aber keine zeitaufwendige Sound-Vermixungsroutine.
Diese lagert man am besten ins Hauptprogramm aus. Mit der IRQ-Routine und dafür spezifizierte Speicheradressen (die man als Flags verwendet kann) steuert man dann ob die Vermixungsroutine etwas tun soll, oder nicht.
Jetzt, wo Du es schreibst, habe ich wohl den ersten Ansatz des polling-mode für AdLib-Musik verstanden... Danke!

Ich denke auch, dass das IRQ - Prinzip eigentlich nicht dazu gedacht war, besonders langdauernde Routinen ablaufen zu lassen, sondern eben nur kurze Unterbrecher. Allerdings ist es auch nicht von vornherein verboten oder führt zu Fehlern - solange eben der Interrupt so schnell abgearbeitet wird, dass für die nachfolgenden noch Zeit bleibt. Ich habe hier schon meine "Soundengine" stundenlang im interrupt laufen lassen. Bis auf dass der PC (nachvollziehbar) sehr langsam wird, gab es nie Probleme (solange die Soundblasterfrequenz nicht zu hoch war).

Aber der von Dir beschriebene Polling-Mode dürfte schon sinnvoller sein, als meine reine IRQ-Lösung.

freecrac hat geschrieben: In einem Beispielprogramm zur Interruptsteuerung aus dem Buch(Kapitel über DSP Programmieren) wird hier eine Speicher-Adresse verwendet wo die Samplelänge eingestellt wird.
Auch wird innerhalb der IRQ-Routine ein Befehle via Port an die SB übertragen. In dieser Unter-Routine wird dieses 200 mal versucht und dabei geschaut, ob es erfolgreich war (mit "in al, dx" und "or al, al" Prüfe Bit 7)
und wenn das Übertragen geklappt hat, dann wird der eigentliche Befehlswert zur SB übertragen.
Die SB muß "ready" sein zum Datenempfang, deswegen die Schleife. Meiner Erinnerung hat Creative - ca. 5 Jahre nach dem Buch - in der Zeit der SB16 eine Schleife von 65535 empfohlen, weil einfach die PCs immer schneller wurden. Das Buch wurde noch für die einfache SB geschrieben, als noch jeder 'nen 286er hatte.

Die mit Bit 7 prüfbare Datenaufnahmebereitschaft war übrigens ein Novum der SB gegenüber der Adlib. Die hatte sowas meines Wissens nicht. Dort musste halt immer eine bestimmte Anzahl von Millisekunden (?) gewartet werden, ohne dass es eine Überprüfungsmöglichkeit gab. Ich habe mal gelesen, dass AdLib wegen der immer schneller werdenden PCs den Beispielcode für die Warteschleife jedes Jahr verändert hat. Am Schluß war der Beispielcode für 486er auf dem 8088 nicht mehr lauffähig, weil der nur noch in der Warteschleife hing...


freecrac hat geschrieben:
Zum Schluss wird erst EOI gesendet, die gepushten Register vom Stack gepoppt und mit "iret" beendet.


Meine Beispielsourcen aus den 90ern - die mir Grundllage für meinen Code waren - waren fehlerhaft. Heute setzen alle da EOI (=int-ACk) am Ende der Interrupt-Seervice-Routine.
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: IRQ-Routine (SB, TP)

Beitrag von wobo »

tom4DOS hat geschrieben:Ich weiß nicht, ob es Dir weiterhilft aber Du kannst Dir mal folgende Pascal-Unit anschauen:
http://homepages.cae.wisc.edu/~brodskye/smix/smix.html
Die macht wohl genau das, was Du zu programmieren versuchst; evtl. kannst Du da etwas "spicken". Ich bin zwar nicht gerade ein Pascal-Programmierer, schon gar nicht bei Soundkarten, aber der Autor von SMIX ruft in seiner Interrupt-Handler-Funktion auch erst die Mixing-Routine auf und sendet zum Schluß das INT-ACK.

Gruß, Thomas
Danke für den Link. Die Pascal-Sourcen von dort (auch die anderen) erscheinen mir sehr srukturiert.

Übrigens: richtigerweise wird das EOI/int-ACK auch bei der SB am Ende der IRQ-Seervice-Routine gesetzt. Meine sourcen waren wieder einmal fehlerhaft.
Antworten