Source file: /~heha/messtech/kreuzt.zip/GRILL/UMSTEP.PAS

unit UMSTEP;
{Unit zur Unterstützung des UMSTEP.386 VxDs von Pascal aus}
{$G+}

interface

const
 UMSTEP_Entry: Pointer=nil;

const
{Folgende Kommandos gibt es:}
 SM_GetVer	=0;	{Versionsnummer holen}
 SM_SetMotor	=1;	{Motor hinzufügen, Parameter setzen/ändern}
			{(AL=ForceAlloc-Flag, ES:BX=Mem)}
 SM_GetMotor	=2;	{Motorparameter holen (AL=Handle, ES:BX=Mem)}
 SM_RemoveMotor	=3;	{Motor entfernen (AL=Handle)}
 SM_SetIntFreq	=4;	{Interruptfr=enz setzen (BX=Frequenz)}
 SM_GetIntFreq	=5;	{Interruptfrequenz holen (BX=Frequenz)}
 SM_Sync	=6;	{Referenzfahrt}
 SM_MoveAbs	=7;	{Absolutbewegung nach CX:DX}
 SM_MoveRel	=8;	{Relativbewegung um CX:DX}
 SM_Stop	=9;	{Soforthalt}
 SM_Free	=10;	{Motorspulen stromfrei schalten}
 SM_GetPosition	=11;	{Position (EDX=CX:DX) und Geschwindigkeit
			{(ESI=DI:SI) erfragen, BX=Frequenz, AH=Flags)}
{Fehlercodes von Isel}
 ME_NoError		=0;
 ME_WrongFunction	=1;
 ME_InMove		=4;
 ME_SoftEnd		=5;
 ME_HardEnd		=7;
 ME_NoRef		=9;
{Eigene Fehlercodes}
 ME_InvalHandle		=50;
 ME_AlreadyAssigned	=51;
 ME_OutOfHandles	=52;
 ME_OutOfMemory		=53;
 ME_InvalPointer	=54;
 ME_InvalPort		=55;
 ME_InternErr		=56;
 ME_NoVxD		=57;

const
{Konstanten für CFlags}
 MC_FreeOnMovEnd=2;	{Spulenstrom abschalten bei normalem Bewegungsende}
 MC_SyncRequired=8;	{Synchronisation vor MOVE ERFORDERLICH}
 MC_Signed	=16;	{Vorzeichenbehafteter Mikroschritt-DAC}
 MC_Table	=32;	{Tabelle statt Funktion (Dreieck<->Sinus)}
 MC_Trapeze	=64;	{Trapezförmiger Strom (Trapez<->"Kurve")}
{Konstanten für Flags}
 MF_InMove	=1;	{Motor in Bewegung}
 MF_InSync	=2;	{Referenzfahrt erfolgt gerade}
 MF_Synced	=4;	{Referenzfahrt war erfolgreich}
 MF_HWECheck	=16;	{Endschalter angestoßen: Referenzfahrt erforderlich!}
 MF_NegDir	=128;	{Negative Bewegungsrichtung}

type
 LongRec=record
  Lo,Hi: Word;
 end;
 PMotor=^TMotor;
 TMotor=record
{Dieser Record kann via GetMotor() abgefragt und SetMotor() gesetzt werden}
  Handle:	Byte;		{Motor-Handle (0=NEUER MOTOR)}
  CFlags:	Byte;		{Konstante Motor-Flags CF_xxxx}
  RefW:		Word;		{Referenztaster-Maske (Low) und XOR (High)}
  PortHWE:	Word;		{Portadresse der Positions-Taster}
  PortA:	Word;		{Portadresse Spule A}
  PortB:	Word;		{Portadresse Spule B}
  CallbackAddr:	Pointer;	{16:16-Rückrufadresse}
  CallbackDS:	Word;		{Datensegment für Callback}
  CallbackUser:	LongInt;	{32-bit-Anwenderdaten}
  MaxSpeed:	LongInt;	{vzl. Maximalgeschwindigkeit [uStep/tick]}
  RefSpeed:	LongInt;	{vzb. Referenz-Geschwindigkeit [uStep/tick]}
  MaxAccel:	LongInt;	{vzl. Maximalbeschleunigung [uStep/tick²]}
  Refpoint:	LongInt;	{vzb. Referenzpunkt nach Sync [mStep]}
  LeftBound:	LongInt;	{vzb. negativer Software-Anschlag [mStep]}
  RightBound:	LongInt;	{vzb. positiver Software-Anschlag [mStep]}
  EndW:		Word;		{Endtaster-Maske (Low) und XOR-Bits (High)}
  BrakeW:	Word;		{Bremsmagnet-Maske (Low) unf XOR-Bits (High)}
  OnW:		Word;		{Einschalt-Maske (Low) unf XOR-Bits (High)}
  PortEAB:	Word;		{Ausgabe-Portadresse (Ein/Aus und Bremse)}
 end;
{Der Callback wird gerufen mit DS=CallbackDS, EDX=CX:DX=Anwender-Daten,
 AL=Handle, AH=Flags (MF_xxxx), ESI=DI:SI=Position}
{Anwendung:
 Position [mStep] = Pos[Grad]*256*Schritte_pro_Grad
 Geschw. [uStep/tick] = Speed[Grad/s]*16777216*Schritte_pro_Grad/Freq
 Beschl. [uStep/tick²] = Accel[Grad/s²]*16777216*Schritte_pro_Grad/Freq/Freq}

function SMGetVer:Word;
function SMSetMotor(Force:Boolean; var MotDesc: TMotor):Byte;
function SMGetMotor(Handle:Byte; var MotDesc: TMotor):Byte;
function SMRemoveMotor(Handle:Byte):Byte;
function SMSetIntFreq(Freq:Word):Byte;
function SMGetIntFreq:Word;
function SMSync(Handle:Byte):Byte;
function SMMoveAbs(Handle:Byte; ToPos:LongInt):Byte;
function SMMoveRel(Handle:Byte; ByStep:LongInt):Byte;
function SMStop(Handle:Byte):Byte;
function SMFree(Handle:Byte):Byte;
function SMGetPosition(Handle:Byte; var Pos,Speed:LongInt;
  var Freq:Word; var Flags:Byte):Byte;
{Anwendung:
 Position [Grad] = Pos/256/Vollschritte_pro_Grad
 Geschwindigkeit [Grad/s] = Speed/256/65536/Vollschritte_pro_Grad*Freq}
const
 VxDName: array[0..10]of Char='UMSTEP.386';
implementation

procedure CallVXD; assembler;
 asm	cmp	LongRec[UMSTEP_Entry].Hi,0
	jz	@@err
	call	[UMSTEP_Entry]
	ret
@@err:	mov	al,ME_NoVxD
 end;

function SMGetVer:Word; assembler;
 asm	mov	ah,SM_GetVer
	call	CallVxD
	xchg	ax,dx
 end;

function SMSetMotor(Force:Boolean; var MotDesc: TMotor):Byte; assembler;
 asm	les	bx,[MotDesc]
	mov	al,[Force]
	mov	ah,SM_SetMotor
	call	CallVxD
 end;

function SMGetMotor(Handle:Byte; var MotDesc: TMotor):Byte; assembler;
 asm	les	bx,[MotDesc]
	mov	al,[Handle]
	mov	ah,SM_GetMotor
	call	CallVxD
 end;

function SMRemoveMotor(Handle:Byte):Byte; assembler;
 asm	mov	al,[Handle]
	mov	ah,SM_RemoveMotor
	call	CallVxD
 end;

function SMSetIntFreq(Freq:Word):Byte; assembler;
 asm	mov	bx,[Freq]
	mov	ah,SM_SetIntFreq
	call	CallVxD
 end;

function SMGetIntFreq:Word; assembler;
 asm	mov	ah,SM_GetIntFreq
	call	CallVxD
	xchg	ax,bx
 end;

function SMSync(Handle:Byte):Byte; assembler;
 asm	mov	al,[Handle]
	mov	ah,SM_Sync
	call	CallVxD
 end;

function SMMoveAbs(Handle:Byte; ToPos:LongInt):Byte; assembler;
 asm	mov	al,[Handle]
	mov	dx,LongRec[ToPos].Lo
	mov	cx,LongRec[ToPos].Hi
	mov	ah,SM_MoveAbs
	call	CallVxD
 end;

function SMMoveRel(Handle:Byte; ByStep:LongInt):Byte; assembler;
 asm	mov	al,[Handle]
	mov	dx,LongRec[ByStep].Lo
	mov	cx,LongRec[ByStep].Hi
	mov	ah,SM_MoveRel
	call	CallVxD
 end;

function SMStop(Handle:Byte):Byte; assembler;
 asm	mov	al,[Handle]
	mov	ah,SM_Stop
	call	CallVxD
 end;

function SMFree(Handle:Byte):Byte; assembler;
 asm	mov	al,[Handle]
	mov	ah,SM_Free
	call	CallVxD
 end;

function SMGetPosition(Handle:Byte; var Pos,Speed:LongInt;
  var Freq:Word; var Flags:Byte):Byte; assembler;
 asm	mov	al,[Handle]
	mov	ah,SM_GetPosition
	call	CallVxD
	push	di
	 les	di,[Pos]
	 mov	es:LongRec[di].Lo,dx
	 mov	es:LongRec[di].Hi,cx
	 les	di,[Speed]
	 mov	es:LongRec[di].Lo,si
	pop	es:LongRec[di].Hi
	les	di,[Freq]
	mov	es:[di],bx
	les	di,[Flags]
	mov	es:[di],ah
 end;


const
 UMSTEP_Device_ID=$3C0E;	{VxD-ID, von Microsoft zugewiesen}
var
 VXDLDR_Entry:Pointer;
 OldExit:Pointer;

{Deinstallation}
procedure NewExit; far; assembler;
 asm
	db	$66
	mov	ax,word ptr [OldExit]
	db	$66
	mov	word ptr [ExitProc],ax
	mov	ax,$0002	{Unload_VxD}
	mov	bx,UMSTEP_Device_ID
	call	[VXDLDR_Entry]
 end;

function Get_UMSTEP_Entry:Word; assembler;
 asm	xor	di,di
	mov	es,di
	mov	bx,UMSTEP_Device_ID
	mov	ax,$1684	{Get Device API Entry Point}
	int	$2F
	mov	ax,es
	mov	LongRec[UMSTEP_Entry].Lo,di
	mov	LongRec[UMSTEP_Entry].Hi,ax
 end;

{Initialisierung}
begin
 asm	call	Get_UMSTEP_Entry
	or	ax,ax		{<>0?}
	jnz	@@e		{ja, statisch geladen!}
	mov	bx,$0027	{VXDLDR-Device-ID}
	mov	ax,$1684
	int	$2F
	mov	ax,es
	or	ax,ax		{<>0?}
	jz	@@e		{nein, wohl kein Windows95?}
	mov	LongRec[VXDLDR_Entry].Lo,di
	mov	LongRec[VXDLDR_Entry].Hi,ax
	mov	dx,offset VxDName
	mov	ax,$0001	{Load_VxD}
	call	[VXDLDR_Entry]
	jc	@@e		{Fehler!}
	push	cs
	push	offset NewExit
	db	$66
	pop	ax
	db	$66
	xchg	word ptr [ExitProc],ax
	db	$66
	mov	word ptr [OldExit],ax
	call	Get_UMSTEP_Entry	{Zweiter Versuch}
@@e: end;
end.
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded