MODULE MousePS2;
IMPORT SYSTEM, Machine, Modules, Objects, Kernel, Inputs;
TYPE
Aux = OBJECT
VAR
p, numb: LONGINT;
buf: ARRAY 4 OF SET;
active: BOOLEAN;
timer: Objects.Timer;
PROCEDURE HandleInterrupt;
VAR b: SET; m: Inputs.MouseMsg; ch: CHAR;
BEGIN {EXCLUSIVE}
Machine.Portin8(64H, ch);
IF SYSTEM.VAL(SET, ch) * {0} = {} THEN INC(ignored); RETURN END;
Machine.Portin8(60H, ch);
IF active THEN
b := SYSTEM.VAL(SET, LONG(ORD(ch)));
IF (p = 0) & (b * {6,7} # {}) THEN
INC(errors)
ELSE
buf[p] := b; INC(p);
IF p = numb THEN
m.keys := {};
IF 2 IN buf[0] THEN INCL(m.keys, 1) END;
IF 1 IN buf[0] THEN INCL(m.keys, 2) END;
IF 0 IN buf[0] THEN INCL(m.keys, 0) END;
m.dx := SYSTEM.VAL(LONGINT, buf[1]);
IF 4 IN buf[0] THEN DEC(m.dx, 256) END;
m.dy := SYSTEM.VAL(LONGINT, buf[2]);
IF 5 IN buf[0] THEN DEC(m.dy, 256) END;
m.dz := SYSTEM.VAL(SHORTINT, buf[3]);
IF 6 IN buf[0] THEN DEC(m.dz, 256) END;
p := 0; m.dy := -m.dy;
Inputs.mouse.Handle(m)
END
END
ELSE
INC(ignored)
END
END HandleInterrupt;
PROCEDURE HandleTimeout;
BEGIN {EXCLUSIVE}
active := TRUE
END HandleTimeout;
PROCEDURE &Init*(rate: LONGINT);
PROCEDURE SetRate(r: LONGINT);
BEGIN WriteAck(0F3X); WriteAck(CHR(r))
END SetRate;
BEGIN
active := FALSE; p := 0;
PollAux;
Machine.Portout8(64H, 0A8X);
SetRate(200); SetRate(100); SetRate(80); SetRate(rate);
WriteAck(0F2X);
IF InAux() # 0X THEN numb := 4 ELSE numb := 3 END;
WriteAck(0E8X); WriteAck(3X);
WriteAck(0E7X);
PollAux;
Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+12);
WriteDev(0F4X);
WriteCmd(47X);
PollAux;
NEW(timer); Objects.SetTimeout(timer, SELF.HandleTimeout, 250)
END Init;
PROCEDURE Remove;
BEGIN {EXCLUSIVE}
Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0+12);
Objects.CancelTimeout(timer)
END Remove;
END Aux;
VAR
errors*, ignored*: LONGINT;
aux: Aux;
PROCEDURE PollAux;
VAR s: SET; i: LONGINT; t: Kernel.MilliTimer;
BEGIN
i := 10;
LOOP
Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
IF (s * {0,1} = {}) OR (i = 0) THEN EXIT END;
Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
IF s * {0,5} = {0,5} THEN Machine.Portin8(60H, SYSTEM.VAL(CHAR, s)) END;
Kernel.SetTimer(t, 20);
REPEAT UNTIL Kernel.Expired(t);
DEC(i)
END
END PollAux;
PROCEDURE InAux(): CHAR;
VAR s: SET; t: Kernel.MilliTimer;ch: CHAR; i: SHORTINT;
BEGIN
i := 10;
REPEAT
Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
IF s * {0,5} = {0,5} THEN
Machine.Portin8(60H, ch);
RETURN ch
END;
Kernel.SetTimer(t, 20);
REPEAT UNTIL Kernel.Expired(t);
DEC(i);
UNTIL i = 0;
RETURN 0X
END InAux;
PROCEDURE WriteDev(b: CHAR);
BEGIN
PollAux; Machine.Portout8(64H, 0D4X);
PollAux; Machine.Portout8(60H, b)
END WriteDev;
PROCEDURE WriteAck(b: CHAR);
VAR s: SET; i: LONGINT; t: Kernel.MilliTimer;
BEGIN
WriteDev(b); i := 10;
LOOP
Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
IF (s * {0,5} = {0,5}) OR (i = 0) THEN EXIT END;
Kernel.SetTimer(t, 20);
REPEAT UNTIL Kernel.Expired(t);
DEC(i)
END;
IF i # 0 THEN Machine.Portin8(60H, SYSTEM.VAL(CHAR, s)) END
END WriteAck;
PROCEDURE WriteCmd(b: CHAR);
BEGIN
PollAux; Machine.Portout8(64H, 60X);
PollAux; Machine.Portout8(60H, b)
END WriteCmd;
PROCEDURE ConfigMouse;
VAR i, rate: LONGINT; s: ARRAY 16 OF CHAR;
BEGIN
errors := 0; ignored := 0;
Machine.GetConfig("MouseRate", s);
i := 0; rate := Machine.StrToInt(i, s);
IF (rate <= 0) OR (rate > 150) THEN rate := 100 END;
NEW(aux, rate)
END ConfigMouse;
PROCEDURE Install*;
BEGIN
IF aux = NIL THEN ConfigMouse END
END Install;
PROCEDURE Remove*;
BEGIN
IF aux # NIL THEN aux.Remove(); aux := NIL END
END Remove;
BEGIN
Modules.InstallTermHandler(Remove);
aux := NIL; Install
END MousePS2.