/*DSO-Kartenansteuerung*/
//#include <stdio.h>
#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 merkwürdigen 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 für 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 kümmert 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 für 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<endadr);
// putchar('\n');
}
void pascal read(WORD endadr, BYTE *k1, BYTE *k2) {
WORD a,s;
// outportb(portbase+6,0); /* RAM-Zähler rücksetzen (nötig??) */
for (a=0; a<endadr; a++) {
outport(portbase+2,a);
s=inport(portbase+2);
if (k1) *k1++=LOBYTE(s);
if (k2) *k2++=HIBYTE(s);
}
}
INITPARAMS test={20000U,{{4,0},{4,0}},{2,0}};
BYTE k1[1000];
void cdecl main(void) {
int i;
init(&test);
start();
wait(1000);
stop();
read(1000,k1,NULL);
for (i=0; i<500; i++) {
printf("%02X ",k1[i]);
}
}
#endif
Detected encoding: OEM (CP437) | 1
|
|