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
|
|