/*DSO-Kartenansteuerung*/ //#include #include "inpout32.h" #define outw DlPortWritePortUshort #define outb DlPortWritePortUchar #include "dso.h" /* 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, 07/04): * Registerbelegung: * Offset Lesen Schreiben * +0 RAM-Adresse LOW Sampleratenteiler LOW * +1 RAM-Adresse HIGH Sampleratenteiler HIGH * +2 Daten Kanal B (Y2) RAM-Adresse LOW * +3 Daten Kanal A (Y1) RAM-Adresse HIGH * +4 - Digital-Steuerung * Bit Funktion * 2..0 Triggerquelle und -polarit„t * 0 A- Y1- * 1 B- (wirklich!) Y2- * 2 A+ (wirklich!) Y1+ * 3 B+ Y2+ * 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) * Bsp: 0F im Scroll-Modus * DF w„hrend Auslesen * 0C w„hrend Samplen (Ext-) * 0F zur Auto-Triggerung, kein +6 * +5 - Analog-Steuerung * Bit Funktion * 2..0 D„mpfung B (Y2) * 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 B (Y1) 0=AC, 1=DC * 6..4 D„mpfung A (Y1) (wie bei B) * 7 Eingangskopplung A (Y2) 0=AC, 1=DC * +6 - Z„hler nullsetzen (scharfmachen) * (keine Daten-Auswertung) * Offenbar: Z„hler anhalten bis Trigger * +7 - Auto-Trigger ausl”sen * (keine Daten-Auswertung) * Offenbar: System starten * * 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. Initialisierung und Betrieb der dscope.exe und dscopescroll.exe: // Programmstart outb(5,0x55); // 1V/div fr beide Kan„le outw(0,0x0000); outw(2,0xFFF0); outb(4,0x07); // Externer Trigger, /CS=LOW, /ADCOE=/WR=LOW outw(2,0xFFF0); // Fenster bauen sich auf outb(5,0x55) outw(0,0x0000); outw(2,0xFFF0); outb(4,0x02); // Kanal 2 + outw(2,0xFFF0); // Fenster verschieben sich outb(4,0xFF); // offenbar: kompletter Halt outb(3,0x80); // Anwesenheits-Test if (inb(1)!=0x80) goto raus; outb(4,0xFF); outb(3,0x78); if (inb(1)!=0x78) goto raus; outb(4,0xFF); outb(3,0x56); if (inb(1)!=0x56) goto raus; // Weiter je nach Betriebsart: Scroll-Modus Normal mit Auto ohne Signal ------------------------------------------------------------------------------- outb(5,0x55) #gleich# ## outw(0,0x0000) outw(0,0x0001) ## outw(2,0xFFF0) ## ## outb(4,0x02) outb(4,0x0A) ## outw(2,0xFFF0) ## ## // zeichnet Nulllinie (aus Daten, die noch gar nicht gesampled wurden!) do; while (inw(0)!=0x7880) outb(3,0x80) forever{ forever{ outb(5,0x55) ## ## outw(0,0x0110) outw(0,0x0001) ## outw(2,0xFFF0) ## ## outb(4,0x0F) outb(4,0xDF) ## outw(2,0xFFF0) ## forever { for(0x7FE0) { ## //alle paar ms: outw(2,0x801E) ## inw(2) = Samples inw(2) Samples ## } } ## // Ab hier keine Aufzeichnung der Portzugriffe auf 0,1,2,3 outb(5,0x55) ## outb(4,0xDF) ## outb(5,0x55) ## outb(4,0x0C) Ext- ## outb(6,0) ## outb(7,0) ## // nach 500 ms outb(5,0x55) outw(2,0xFFF0) outb(4,0x0F) outw(2,0xFFF0) outb(7,0) outb(5,0x55) outw(2,0xFFF0) outb(4,0x0C) outw(2,0xFFF0) // nach 150 ms outb(3,0x80) outb(5,0x55) outw(2,0xFFF0) outb(4,0xDF) outw(2,0xFFF0) } } */ static WORD mkatt(CHANNEL*ch){ /* erzeuge att-Nibble */ BYTE att; att=ch->gain; if (att>=4) att++; if (!ch->coupling) att|=0x08; /* DC-Kopplung (Kondensator überbrücken) */ return att; } static WORD control; void _CDECL init(INITPARAMS*ip) { BYTE t; outw(0,ip->samplediv); /* 2 Bytes auf einem Schlag! */ t=(BYTE)((ip->trigger.source^1)<<1); // Bit 2..1: Kanal 0,1,2 if (ip->trigger.edge) t|=1; // Bit 0: Polarität if (ip->samplediv) t|=8; // Bit 3: Takt vom Teiler if (t==1 || t==2) t^=3; /* 1 und 2 vertauschen wegen idiotischer FPGA */ t|=0xF0; control=(WORD)(t | (mkatt(&ip->channel[0])<<8) | (mkatt(&ip->channel[1])<<12)); // outport(portbase+2,0xFFF0); /* weiá nicht... */ outw(4,control); // outport(portbase+2,0xFFF0); /* weiá nicht... */ } void _CDECL start(void) { control&=~0x0070; // outw(2,0xFFF0); /* weiá nicht... */ outw(4,control); outb(6,0); // outw(2,0xFFF0); /* weiá nicht... */ outb(7,0); /* Auto-Trigger */ } void _CDECL stop(void) { control|=0x0050; outw(4,control); } #if 0 void pascal wait(WORD endadr) { WORD w/*,x*/; do{ w=inw(0); // x=inw(2); // printf("%04X %02X %02X %04X\r",w,LOBYTE(x),HIBYTE(x), control); } while (w