/*DSO-Kartenansteuerung*/ #include #include /* Ergebnisse der Untersuchung der Signalleitungen am 26.02.2002: * Der Taktteiler arbeitet mit Teilerwert 0 gar nicht und teilt bei * Wert 1 effektiv durch 2. * Bei +4:Bit3=0 wird der Takt von 20MHz direkt an ADC-CLK und RAM-WE * (in gleicher Phasenlage) weitergeleitet, * ansonsten ein (unsymmetrischer) Takt von max. 10MHz (aktiv LOW, * viel HIGH. * Der ADC liefert bei 20MHz ein stabiles Signal bei ADC-CLK=LOW; * der RAM bernimmt lt. Datenblatt das Signal mit der steigenden * Flanke von RAM-WE. * Der ADC bekommt permanent Taktimpulse, auch wenn nichts gesampelt wird. * * An der merkwrdigen Diode (bei der ich zun„chst an eine Auto-Trigger- * Verz”gerung dachte, weil dem Entwickler die Flipflops ausgegangen * sein k”nnten) liegt die RAM-Adresse A15, mithin die Ende-Kennung an- * und lieáe sich so auch ohne Umprogrammierung des Chips als Interrupt- * Ausgang verwenden (z.B. IRQ3 (COM2), IRQ4 (COM1), IRQ5 (Soundkarte), * IRQ7 (LPT1), IRQ2 (=IRQ9)) - mit einem ordentlichen VxD auch ohne Probleme * gemeinsam mit den anderen Ressourcen. * Auto-Trigger wird hier also g„nzlich per Software-Verz”gerung gemacht. * Bisweilen lieá sich die Karte trotz Auto-Trigger nicht starten; * aber bei Triggerquelle-Einstellung "extern" ging es dann doch. * Dabei tut sich noch der (auch schon vorher im Programm beobachtete) Bug * hervor, dass bei Umstellung der Triggerflanke ein Trigger-Impuls * "gesehen" wurde. * Ein Bit der gesamten Register-Bank konnte ich nicht ordentlich * identifizieren: +4:Bit5. */ /* Ergebnisse der Untersuchung des Programms (02/02): * Registerbelegung: * Offset Lesen Schreiben * +0 RAM-Adresse LOW Sampleratenteiler LOW * +1 RAM-Adresse HIGH Sampleratenteiler HIGH * +2 Daten Kanal A RAM-Adresse LOW * +3 Daten Kanal B RAM-Adresse HIGH * +4 - Digital-Steuerung * Bit Funktion * 2..0 Triggerquelle und -polarit„t * 0 A- * 1 B- (wirklich!) * 2 A+ (wirklich!) * 3 B+ * 4,6 Ext- * 5,7 Ext+ * 3 Takt-Quelle fr RAM-CE und ADC-CLK * 0 Direkte Takt-Weiterleitung 20MHz * 1 Takt aus Taktteiler (max. 10MHz) * 4 RAM-CE: * 0 RAM-CE=LOW (und keine Triggerung) * 1 RAM-CE=HIGH (aber LOW-Sampleimpulse) * 5 ? (FPGA-intern) * 6 RAM-WR und ADC-OE, 1=HIGH, 0=LOW * 7 - (ohne Funktion) * +5 - Analog-Steuerung * Bit Funktion * 2..0 D„mpfung A * 0 0,05 V/Div * 1 0,1 V/Div * 2 0,2 V/Div * 3 0,5 V/Div * 4 - (verboten) * 5 1 V/Div * 6 2 V/Div * 7 5 V/Div * 3 Eingangskopplung A 0=AC, 1=DC * 6..4 D„mpfung B (wie bei A) * 7 Eingangskopplung B 0=AC, 1=DC * +6 - Z„hler nullsetzen (scharfmachen) * (keine Daten-Auswertung) * +7 - Auto-Trigger ausl”sen * (keine Daten-Auswertung) * * Die Triggerkopplung ist immer AC. * Es gibt keinen Pr„trigger. * Auch eine GND-Kopplung gibt es nicht. * Entsprechende Funktionen werden in der Software nachgebildet! * Damit ist kein echter Pr„trigger bzw. Gleichspannungs-Triggerkopplung * m”glich, obwohl komplett im FPGA realisierbar. * * Es erfolgt KEINE Auto-Inkrementierung der Adresse beim Lesen; * so kann der effektive "rep insw"-Befehl nicht zur Sampledaten-Abholung * verwendet werden. Geschwindigkeiten siehe PROFILE.PAS. * Die Originalroutine braucht auf einem 486/66 555 ms zum Einlesen. * Die Register k”nn(t)en ohne weiteres auch mit wort- und dwordweisen * Befehlen angesprochen werden; die ISA-Buslogik kmmert sich um die * Details. Es geht etwas schneller als mit 8-bit-Befehlen. */ /* Wie man den viel-beinlosen Schaltkreis auswechselt: * * Man nehme etwas Abschirmblech und decke damit die Leiterplatte so ab, * dass nur noch der Schaltkreis und die vier unmittelbar benachbarten * Bauelemente herausgucken. * Dann legt man das Ganze derart auf einen Tisch, dass der Schaltkreis * nach unten ber die Tischkante (oder besser eine Tisch-Ecke) ragt. * Das ganze mit einem Gewicht (Schraubstock, Feilkloben) stabilisieren. * Auf dem Fuáboden etwas Schaumstoff ausbreiten. * Wer vorsichtig ist, klebt auf den Schaltkreis noch ein passendes * Stck Glaswolle o.„. nicht brennbares Isoliermaterial. * Mit einem Stift, Schraubendreher oder Pinzette in der linken * und einem auf maximale Temperatur eingestellten Baumarkt-Heiáluft-Gebl„se * in der rechten Hand wird der Schaltkreis von unten angeblasen und mit dem * Stift von der Leiterplatte abgestoáen. (Die Schwerkraft berwindet die * Adh„sion nicht!) * Schaltkreis auf eine kalte Fl„che zur schnelleren Abkhlung legen - fertig. * Nun noch die L”tpads mit Entl”tlitze von den Zinnbergen befreien. * * Als Neubestckung kommt nur eine SMD-Schaltkreisfassung in Frage * (gibt's bei Reichelt fr ca. 0,60 î) * Diese wird mit sehr spitzem L”tkolben einbeinig angel”tet, ausgerichtet * und danach verl”tet. Abgeschr„gte Ecke richtig setzen! Kein Pin vergessen! * Unterm Mikroskop kontrollieren, indem man auf jede L”tfahne drauf- und * seitlich drckt, ob sie fest ist. * Die (an sich bessere) Methode mit Zinnpaste und Heiáluft oder Ofen * wurde nicht erprobt. * Wenn alles OK ist, sollte der vorher ausgewechselte IC in dieser Fassung * sofort funktionieren. * Zum Herausnehmen ist ein PLCC-Ausziehwerkzeug ein Muss! * * P.S.: * Bei mir ging erst mal nichts; aber aus irgendeinem Grund war zur selben * Zeit der Quarzoszillator kaputtgegangen. */ /* Nach dem Neubrennen des FPGA (nur beim Hersteller, aber immerhin kostenlos): * Offset Lesen Schreiben * +0 Daten Kanal A Sampleratenteiler LOW * +1 Daten Kanal B Sampleratenteiler HIGH * +2 Daten Kanal A Inkrements * Bit Funktion * 2-0 Lese-Inkrement (Zweierpotenzen) * 5-3 Schreib-Inkrement (Zweierpotenzen) * 7-6 Pr„trigger 0, 25, 50, 75% * +3 Daten Kanal B DC-Trigger-Wert * +4 Sample-Z„hler LOW Digital-Steuerung * Bit Funktion * 0 Triggerflanke * 1 A/B-Auswahl * 2 Extern-Auswahl * 3 DC (digital)/AC(analog)-Triggerkopplung * 4 ? * 5 Samplen/Auslesen * 6 Interrupt nach jedem Sample * 7 Interrupt am Ende * +5 Sample-Z„hler HIGH Analog-Steuerung * +6 RAM-Z„hler LOW Kompletter Reset? * +7 RAM-Z„hler HIGH Auto-Trigger? * * Die Daten in vierfacher Ausfertigung sollen Einlesen mit "rep insd" * erm”glichen; das Lese-Inkrement wird nach Lesen von Kanal B angesetzt. * (Das Lese-Inkrement erlaubt das Auslesen geringerer Datenmengen * zum nachtr„glichen Zoom - spart enorm Rechenlast!) * Das Schreib-Inkrement erlaubt eine Teil-Ausnutzung des RAM * bei besonders geringen Latenzzeiten (bei Ger„testeuerungen) * Die RAM-Adresse ist wegen echtem Pr„trigger nicht von Belang, denn es * wird stets "im Rundumverfahren" eingelesen. * Der Sample-Z„hler "ersetzt" die RAM-Adresse (l„uft parallel dazu); * auch hier ist das Ende bei 8000h erreicht (mit Interrupt). * Bei Start oder beim Erreichen von 2000h, 4000h bzw. 6000h * (je nach Pr„trigger) stockt dieser Z„hler, * w„hrenddessen der RAM-Z„hler munter weitermacht und der RAM Daten einliest, * und bei Triggersignal geht's weiter bis zum o.g. Endwert 8000h; * dann h„lt auch der RAM-Z„hler an und steht gerade am Anfang der * zu lesenden Sampledaten (i.d.R. nicht Null!). * Das Programm sollte stets alle Daten so auslesen, dass der RAM-Z„hler * danach an der gleichen Stelle steht! * Die Gleichspannungs-Triggerung erfolgt im FPGA durch (digitalen) * Vergleich mit einem Referenzwert (warum nicht gleich so?) * Die genaue Bedeutung der Bits bei "Digital-Steuerung" muss sich noch * herauskristallisieren. */ typedef unsigned char BYTE; typedef unsigned short WORD; WORD portbase=0x2C0; WORD control; #define INVERT 0x80 #define AC 0x01 #define AUTO 0x40 #define LOBYTE(x) (((BYTE*)(&x))[0]) #define HIBYTE(x) (((BYTE*)(&x))[1]) typedef struct{ BYTE gain; BYTE coupling; }CHANNEL; typedef struct{ BYTE source; BYTE coupling; }TRIGGER; typedef struct{ WORD samplediv; CHANNEL channel[2]; TRIGGER trigger; }INITPARAMS; WORD mkatt(CHANNEL*ch){ /* erzeuge att-Nibble */ BYTE att; att=ch->gain; if (att>=4) att++; if (ch->coupling & AC) att|=0x08; return att; } void init(INITPARAMS*ip) { unsigned char t; outport(portbase+0,ip->samplediv); /* 2 Bytes auf einem Schlag! */ t=ip->trigger.source<<1; if (ip->trigger.coupling & INVERT) t|=1; if (t==1 || t==2) t^=3; /* 1 und 2 vertauschen wegen idiotischer FPGA */ t|=0xF8; control=t | (mkatt(&ip->channel[1])<<12) | (mkatt(&ip->channel[0])<<8); // outport(portbase+2,0xFFF0); /* weiá nicht... */ outport(portbase+4,control); // outport(portbase+2,0xFFF0); /* weiá nicht... */ } void start(void) { control&=~0x0070; // outport(portbase+2,0xFFF0); /* weiá nicht... */ outportb(portbase+4,control); // outport(portbase+2,0xFFF0); /* weiá nicht... */ outportb(portbase+6,0); outportb(portbase+7,0); /* Auto-Trigger */ } void stop(void) { control|=0x0050; outportb(portbase+4,control); } void pascal wait(WORD endadr) { WORD w,x; do{ w=inport(portbase+0); x=inport(portbase+2); printf("%04X %02X %02X %04X\r",w,LOBYTE(x),HIBYTE(x), control); } while (w