Source file: /~heha/basteln/PC/oszi/oszi.zip/src/dso.c

/*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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded