Aufmacher 

PCI-Recorder

Audio-Schnittstellenkarte für den PCI-Bus, Teil 3

Note: This is not an original Elrad page, but a reconstruction from the article in ELRAD 5/97. So most typos are mine:-) (fjk)

Martin Kirst, Uwe Kirst


| Hauptseite| Artikel | Tips und Tricks | Liefernachweis und Treiber | Literatur |

Die Komponente 'arbiter'
Paritätserzeugung für Lesezugriffe
Synchronisation Audio- und PCI-Takt
Die Audiologik
Dait und Counter
Prescaler
Globaler Reset
Zum Designablauf
Registerprogrammierung
Windows 95 - Plug and Play
Kompatibilität

Die konfliktfreie Handhabung von PCI- und Audio- Transaktionen ist gegeben, wenn man voraussetzt, daß ein PCI-Burstzugriff wesenlich weniger Zeit in Anspruch nimmt, als zwischen zwei Abtastwerten liegt. Tritt während eines Burstes der Fall ein, daß ein Abtastwert im Schieberegister zur Abholung bereitsteht, wird einfach die Beendigung des Burstes abgewartet.

Die Komponente 'arbiter'

Der umgekehrte Fall, daß während eines Transfers von Audiodaten von und zu dem Schieberegister eine PCI-Anforderung eingeht, ist unkritisch. Das DEVSEL-Signal wird wie gewöhnlich erzeugt, das TRDY Signal jedoch bis zum Zurücknehmen des LOC-GNT-Signals des Arbiters zurückgehalten. In diesem Fall hat der Target maximal vier zusätzliche Wartezyklen eingelegt, bis die Audiooperation beendet wird. Treffen Audio- und PCI-Anforderung gleichzeitig ein, werden die Audiodaten beforzugt abgefertigt.

Paritätserzeugung für Lesezugriffe

Die Paritätserzeugung ist im Gegensatz zur Paritätsprüfung auf dem PCI-Bus nicht optional und wird von der 'parity'-Komponente vorgenommen. Die Parität wird über die kombinierte Daten-und Adreßleitungen und die Byte-Enable-Signale gebildet; das Paritätsbit eilt den Daten um einem Taktzyklus nach. Die Paritätsberechnung erfolgt in zwei Taktzyklen: In der ersten Stufe werden vier Teilsummen gebildet, die jeweils acht Datenleitungen XOR-verknüpfen. Mit dem zweiten Taktwerden die vier Teilsummen mit den Byte-Enable-Leitungen verquicket. Man kann sich mehrere Taktzyklen für die Berechnung Zeit lassen, da die Daten intern schon bekant sind, befor sie auf den PCI-Bus gegeben werden.

Synchronisation Audio- und PCI-Takt

Das Audioteil und die PCBB arbeiten mit unterschiedlichen Taktnetzwerken. Während der PCI-Takt durch den Rechner, in dem die Karte steckt, vorgegeben ist und meist zwischen 25...33 MHz liegt, gewinnt der Audioteil seinen Takt aus dem eingehenden seriellen Datenstrom mit Hilfe einer PLL-Synchronisation zurück oder kann mit den auf der Karte bestückten 12,288- oder 5,6448-MHz- Quarzoszillatoren betrieben werden. Um fehlerlosen Datenaustausch sicherzustellen, müssen Vorkehrungen zur Synchronisation getroffen werden. Da der Audiotakt wesentlich langsamer läft als der PCI-Takt, wird ein mit Audiotakt erzeugtes Requestsignal von einer Schaltung zur Flanken-erkennung mit PCI-Takt abgetasted. Zwei Flipflops merken sich den Pegel der Requestleitung für zwei PCI-Perioden und lösen bei einem High-Low-Wechsel eine Audioanforderung durch Setzen des LOC_REC-Signals aus.

Die Audiologik

Zur Seriell-Parrallel- und Parallel-Seriell-Wandlung der Audiodaten wurden das schon erwähnte 32 Bit breite Schieberegister herangezogen. Das Design unterstützt neben 16-Bit-Mono und -Stereo auch 24-Bit Formate, wobei ein 24-Bit-Wort in 32 Bits untergebracht ist. Der Windows-95-Treiber unterscheidet zwischen 16-, 24-, und 32-Bit-Formate des Treibers sind bevorzugt zu verwenden, da die 24-Bit-Unterstützung nur mit erheblichem zusätzlichen Softwareaufwand realisiert werden kann, Mit Hilfe aufwendiger Assemblerkodierung müssen zeitkritische Kopierroutinen im Treiber 32-Bit-Worte in 24-Bit-Worte umwandeln. Die Hardware legt ein 24-BitWort MSB-bündig im Schieberegister ab, damit eine vorzeichenrichtige Erweiterung entfallen kann.

Durch das Pipelining sind Aufnahme- und Wiedergabe-daten um 2 x 32 Bit konstant gegeneinander versetzt. Würde man ein Pipeline-Register weniger vorsehen, würde sich der rechte und der linke Kanal im 32-Bit-Modus vertauschen. Die hier vorgestelte lösung besitzt diesen nachteil nicht.

Dait und Counter

Ein kompletter Digital Audio Transmitter (DIT) konnte besonders elegante formuliert werden und wurde im Modul 'dait' untergebracht. Im Abhängigkeit eines 7-Bit-Zählers, der mit 128facher Abtastfrequenz läuft, wird in den Zählerstellung 0..7 die Präambel, in 8..55 ein biphasenkodiertes 24-Bit-Datenwort und in 56-63 vier weitere Bits (Paritätsbit, Kanaler-Status-Bit, und Validity-Bit) erzeugt.

Das gleiche Schema wiederholt sich in den Zählpositionen 64...127 für den zweiten Kanal. Die Prëambel dient der Synchronisation und verletzt deshalb die Biphasenkodiering. Eine Folge von 192 Channel-Status-Bits bildel ein Kanalstatusblock.

Die Kanalstatusdaten tragen unter anderem Informationen über die Abtastfrequenzen, werden aber sonst mit Null initialisiert.

Prescaler

Die Komponente 'prescaler' ist für die Takterzeugung des Audiomoduls zuständig. Das Crystal-IC prüft die tatsächlich angelegte Abtastrate anhand einer Referenzfrequenz (6,144 MHz). Das Ergebnis des Frequenzkomparators steht dem FPGA über die Eingange f0... F2 zur Verfügung. Falls der DIR (Digital Interface Receiver) gültige Daten ausgibt und die gewünste Abtastrate mit der tatsächlich anliegenden übereinstimmt, schaltet 'prescaler' in den PLL-Modus und synchronisiert sich auf das Eingangssignal. In allen anderen Fällen wird die benötigte Taktrate mit Hilfe von zwei Quartzoszillatoren gewonnen. Die 128fache Frequenz von 32 kHz/48 kHz erhält man durch Teilung von 12,228 durch drei/zwei.

Globaler Reset

Es ist zwingend nötig, daß alle Flipflops in einem definierte Anfangszustand ihre Arbeit beginnen; dazu gibt es zwei Möglichkeiten:

  1. Verdrahtung der Reset-Leitung jedes Flipflop über normale Routingressourcen.
  2. Verwendung des im XILINX FPGA vorhandenen globaler Set/Reset-Netwerkes (GSR).
Die erste Möglichkeit sollte man vermeidem, da dabei unnötig Ressourcen verschwendet werden. Je nach Syntheseprogramm gibt es verschiedene Arten, das globale Reset-Netzwerk einzubinden. Der Synopsys-PFGA-Express ist in der Lage, das GSR automatisch unter der Voraussetzung zu verwenden, daß es eine Leitung gibt, die alle Flipflops der Schaltung asynchron setzt beziehungsweise zurücksetzt.

Eine andere Möglichkeit, die immer funktionerende sollte, is die, mit einer speziellen Komponente (Hardmakro) das Signal zu markieren, das einen globalen Reset auslösen soll. Die XILINX-Komponente dazu heißt 'Startup' und hat einen Eingang, der mit 'GSR' bezeichnet wird. Dieses Hardmakro bewirkt, daß alle Flipflops der Schaltung bei Setzen des GSR-Einganges zurückgesetzt werden. Bei Einschalten der Betriebsspannung werden alle Flipflops unabhängig vom GSR-Eingang ebenfalls über das globale Setz-/Rücksetz-Netswerk initalisiert.

Wenn das Hardmakro zum Setzendes Startzustandes der Flipflops verwendet wird, kann die Schaltung mit einer normalen VHDL-Simulation nicht mehr getested werden, weil das Initialiseren der Flipflops nicht explizit im VHDL-Quelltext enthalten ist.

Die Vermeidung des Startup-Makros hat unter Synopsys-FPGA-Express den Vorteil, daß sich der Quellcode direct simulieren l&aulm;ßt. Weil jedoch die dann zusätzlich notwendigen Reset-Leitungen den Sourcecode unübersichtlich machen, wurden sie hier nicht verwendet und statt dessen das XILINX-Hardmakro zur Markierung der Reset-leitung verwendet.

Ein weiterer Vorteil des FPGA-Express von Synopsys ist, daß er die komplexen I/O-Zellen automatisch mappen, also von sich aus Flipflops in I/O-Zellen verlegen kann, wenn ein Aus- oder Eingang mit dem Flipflop verbunden ist.

Zum Designablauf

Die Pinbelegung des FPGA wurde fest vorgegeben und nicht automatisch von der XILINX-Software zugewiesen. Von dieser Vorgehensweise wird meist abgeraten, da eine ungünstige Pinbelegung dazu führen kann, daß das Routing der Logik aufgrund der begrenster Chip-internen Resourcen nicht mehr möglich ist. Die Anordung der PCI-Bussignale erzwingt jedoch ein bestimmtes Chip-Pinout, da alle Leitingen möglichst kurz ausgelegt werden m&ssen. Auch die Plazierung der restlichen nicht-PCI-Signalen wurde vorgegeben, um ein einfaches Platinenlayout zu erhalten. Anfangs war eine 4lagige Platinen geplant, wobei die inneren beiden Lagen der Stromversorgung dienen sollten. Es stellte sich jedoch heraus, daß zwei Lagen ausreichen und auch hier niederohmige Versorgungsflächen realiseert werden können. Das handoptimierte Platinenlayout und Chip-Pinout sind gut aufeinander abbgestimmt.

Registerprogrammierung

Der Zugriff auf die Hardware wird vom Windows-95-Treiber geregelt. Ein directes Ansprechen ist nicht empfehlenswert und bereitet einiges Kopfzerbrechen, wie während der Treiberentwicklung feststellbar war. Wer sich nicht bestens in der Protected-Mode-Programmierung (Stichworte: Paging und Descriptortabellen) auskennt, kommt hier nicht weiter. Außerdem sind Kenntnisse über das Konfigurieren einer PCI-Bus-Karte (z.B. über BIOS-Aufrufe oder über die Hardware direct) erforderlich. Die Schwierigkeit besteht darin die zugeteilte physikalische Adresse der Karte und den Interrupt zu erfragen und sie in einen gültigen Selektor umzuwandeln. Da der Kartenspeicher größer als 64 KByte ist, sind unter Umständen außerdem 32-Offsets mit Hilfe von Präfixen zu erzwingen. Echte 32-Bit-Programma können die Hardware über lineare 32-Bitt-Adressen ansprechen. Auf diese Weise ist es gelungen, für erste Versuche ein einfaches Wiedergabe-Programm zu schreiben, das nur aus weinige Zeilen C++-Quelltext besteht. Diesen Programm verzichtete ganz auf die Verwendung von Interrupts und das Umkopieren der Audiodaten aus dem Kartenspeicher in einen andere Memory-Bereich.

Bit87 654 321 0
Bedeutung>Resetimp1imp0 freq1freq0SELMode24 MonoStart

Bild 8. Die Belegung des Steuerregister bei Schreibzugriffen.

Um die Karte unter Windows eizusetzen, greift man am besten auf das Windows-API zurück, wie schon im Artikel zur 'Take Five'-Karte beschrieben. Als angenehmer Nebeneffekt ergibt sich dann, daß das Programm unabhängig von der verwendeten Hardware ist. Für ganz hartgesottene Programmierer möchten wir an dieser Stelle die Registerprogrammierung erlätern. Das Funktionsprinzip der Karte ist sehr einfach und kann in wenigen Worten zusammengefaßt werden.

Aufnahme und Wiedergabe finden immer gleichzeitig statt (Bild 14). Möchte man trotzdem nur aufnehmen und sich nicht weiter um die Wiedergabe kümmern, hat man automatisch eine Art von verzögerter Hinterbandkontrolle aktiviert. Die Aufnahmedaten sammeln sich im Ringbuffer (SRAM) der karte und werden mit 128 KByte Verzögerung (circa 1 s) auf den Ausgang gegeben, bevor sie von neuen hereinkommenden Daten überspielt werden. Der Zähler des Ringbuffers kan mit eigenen Bits im Steuerregister beeinflußt werden: man kann die aktuelle Position auslesen (Bits 0-16), ihn zurücksetzen (Reset-Bit) und starten oder stoppen (Startbit).

freq1freq0Abtastrate
00PLL-Modus 1
0132 kHz
1044,1 kHz
1148 kHz
1 wird in allgemeines nicht benötigt, siehe Text

Bild 9. Kodierung der Abtastrate

Im einfachsten Fall setzt man für eineAufnahme das Startbit, fragt in regelmaßigen Abständen die Position des Audiozählers ab und kopiert die aufgenommenen Daten aus den karteneigen SRAMs in den Hauptspeicher oder legt sie gleich auf der Festplatte ab.

Imp1Imp0Eingang
00Optischer Eingang
01Koaxialer Eingang
10Interner CD-Eingang
11Interner CD-Eingang

Bild 10. Der Eingangswahlschalter

Hat man noch freie Interrupts zur Verfügung, sollte man der Karte einen davon spendieren. Nach einem Start erzeugt die Karte in 16-KByte-Abständen regelmäßig einen Interrupt, um dem Rechner mitzuteilen, er möge die Daten abholen. Im Steuerregister ist ein IRQ-Bit vorgesehen, das darüber Auskunft gibt, ob der Interrupt von der Audiokarte erzeugt wurde. Interrupt-Sharing ist so mölich. Ein Interrupt muß durch einen Schreibzugriff auf das Steuerregister quittiert werden.

Bild 14. ...

Für die Wiedergabe werden gü Audiodaten ins SRAM kopiert und enschließend durch das Setzen des Startbits der Audiozähler in Gang gesetzt. Der Aufnahme-/Wiedergabemodus kann durch einige Bits im Register gesteuert werden. Das Format wird durch Mono und Mode24 festgelegt. Aufnahme und Wiedergabe erfolgen, wie bei Soundkarten üblich, immer mit dem gleichen Format und der gleichen Abtastrate. Mit der SEL-Leitung kann man auf direkten Digital-Durchgang schalten, falls die Karte nicht in Betrieb ist. Dies ist auch die Default-Einstellung, in der sich die Karte nach dem Booten befindet. Bei der Frequenzwahl ist eine Besonderheit zu beachten. Neben den Abtastfrequenzen 32 kHz, 44,1 kHz und 46 kHz kan der PLL-Mode gew*auml;hlt werden. Man sollte es jedoch vermeiden, explizit in den PLL-Modus zu schalten, da auch schon in den drei anderen Frequenzstellungen sich die Schaltung auf das Eingangssignal synchronisiert, falls die gewählte Frequenz mit der tatsächlichen übereinstimmt. Mit dem KMODE-Bit kann überprüft werden, ob die Schaltung sich auf das Eingangssignal synchroniert hat. Schaltet man hingegen in den PLL-Modus, geht die Abtastfrequenz verloren.

Bei der Registerprogrammierung sollte man bedenken, daß der gleichzeitige einzatz vom Windows-95-Treiber und eines selbstgeschriebenen Programms prinzipiell nicht funktionieren kann, da die Interruptroutine des Treibers beim Auftreten unerwarteter Interruptanforderungen die Schaltung sicherheitshalber abschaltet.

Windows 95 - Plug and Play

Das Konfigurrieren der Karte wird beim Hochfahen des Rechners vom BIOS vorgenommen. Windows 95 übernimmt in der Regel die Einstellungen und ver*auml;ndert sie nur, falls Hardwarekonflikte erkantt werden. Nicht-PCI- und Windows-95 konforme Patch-Mechanismen, die die Vorgaben der Basisadresse und des Interrupts eigenhändig verändern, sind nicht vorgesehen. Steckt man die karte in einen Windows-95-rechner, erkannt der Configuration-Manager (CONFIGMG.VXD) eine neue Hardware durch Aufrufen von speziellen Treibern, den sogenannten Bus-Enumeratoren. Der VxD-Treiber, der in unserem Fall die Hardwareerkennung durchfürt, ist der PCI-Bus-Enumerator. Er erzeugt für jede PCI-Hardware Einträge im Registry (DEVNODs) im Zweig HKEY_LOCAL_MACHINE\Enum\PCI\. Für jedes Gerät gibt es zwei Einträge (sog. Keys), einen Hardware-Key und einen Software-Key. Der Software-Key der hier vorgestellten Karte findet sich unter HKEY_LOCAL_MACHINES\System\Current ControlSet\Services\Class\MDIA.

Die Hardwareerkennung der Karte duch Windows 95 ist unabhangig von der selbstentwickelten Treibersoftware. Der Programmieraufwand beschränkt sich auf das Bereitstellen von zwei Treibern: einem virtuellen Gerätetreiber audio32.VxD (der die PCI-Konfiguration der Karte ermittelt) und dem eigentlichen Treiber audio32.drv, der den Datenflu&szuml; regelt.

Ganz grob läßt sich die Funktionsweise des virtuellen Gerätetreibers so beschreiben: Der Configuration-Manager übermittelt ihm die Meldung CONFIG_START. Daraufhin erfragt er die der Scahltung zugeteilte (physikalische) Basisadresse und die IRQ-Zuordnung vom Configuration-Manager. Der Treiber audio32.VxD ermittelt dann mit Hilfe des Aufrufs VMM_MapPhysToLinear die lineare Basisadresse und generiert einen Segment-Selector mit dem VMM-Call_Allocate_GDT_Selector. Der virtuelle Gerätetreiber besitzt eine selbstdefinierte Schnittstelle, über die er mit dem audio32.drv-Treiber kommunizieren kann. So können die Parameter Selector, physikalische sowie lineare Adresse und IRQ übermittelt werden. Für den Speicherzugriff wichtig ist nur der Selector, da Soundkartentreiber unter Windows 95 nach wie vor 16-Bit-Programma darstellen. Die Kopierroutinen im Treiber sind mit Hilfe des 32-Bit-Befehls REP MOVSD realisiert worden, um optimale Performance zu erreichen.

Kompatibilität

Bei ersten Versuchen mußte mit Entsetzen festgestellt werden, daß die Karte nur in 50% aller Rechner einwandfrei lief. Der Fehler lag darin, daß die IO-Blocke auf 'slow' und 'delay' eingestellt waren. so daß das Timing der Ein- und Ausgangleitungen nicht mehr PCI-Konform war. Nach dem Umprogrammieren auf 'fast' und 'nodelay' funktionierte die Karte ohne Tadel nicht nur in in den Verbreiteten HX-Pentium-Boards, sondern auch in einige 'Exoten'.

Unter den Testkandidaten befanden sich Boards von Asus, MSI, Chaintech, ein Dual-Prozessor-Board von Tyan und ein Billig-Pentium-Rechner von Vobis. Wer ein aktuelles Plug&Play-Bios sein Eigen nennt, wird sich über die kinderleichte Installation freuen: Karten einstecken, beim Booten von Windows 95 die automatische Hardwareerkennung und Treiberinstallation mit 'Ok' bestätigen, fertig. Bei älteren 486-Boards ist es ratsam, erst einmal einen Blick ins BIOS zu werfen. Hier kann die manuellen Zuordnung einzelner (ISA-)IRQs zu PCI-Slots erforderlich sein.

Uwe Kirst

hat sein Physik-Studium an der Uni Kiel erfolgreich beendet (und ist jetzt auf Stellensuche).

Martin Kirst

studiert Elektrotechnik an der TU-Braunschweig im 5. Semester; sein Bruder