evo koda:
Code:
unit PS2_Mouse;
{interface }
type TMouseData =
record
Keys: byte;
DeltaX: integer;
DeltaY: integer;
DeltaZ: integer; // Scrollwheel
end;
function Ps2_Mouse_Init: boolean;
// Initializes the Mouse Ps2 library and resets the mouse.
// Returns true if a "Mouse selftest passed" code is received from the Mouse, else false.
// Also enables the ScrollWheel (if any present).
function Ps2_Mouse_ReadData(var MouseData: TMouseData): boolean;
// Reads the PS2 mouse data into "MouseData".
// MouseData.Keys returns the pressed keys (one bit for every key)
// MouseData.DeltaX returns the delta of the X value (hor position) with respect to the previous data
// MouseData.DeltaY returns the delta of the Y value (vert position) with respect to the previous data
// MouseData.DeltaZ returns the delta of the Scrollwheel value with respect to the previous data
procedure Ps2_Mouse_Write(var Values: array[2] of byte; Count: byte);
// Writes "Count" bytes out of "Values" to the PS2 Mouse. No reply expected here.
// The list of valid commands can be found in: http://www.computer-engineering.org/ps2mouse/
procedure Ps2_Mouse_Write_Read(var Command: array[5] of byte; CountWrite: byte; var Reply: array[4] of byte; CountRead: byte);
// Same as "Ps2_Mouse_Write" above, but after the write operation "CountRead" bytes are read from the mouse into "Reply".
function Ps2_Mouse_Reset: boolean;
// Resets the Mouse and waits (with a timeout of 2 seconds) for the "selftest passed" acknowledge.
// Returns true if the "selftest passed" was acknowledged by the Mouse, otherwise false.
// Remark: the Mouse also resets itself (and does a selftest) at power up time (see "Ps2_Mouse_Init").
function Ps2_Mouse_ScrollWheel_Present: boolean;
// Returns true if the mouse has a scrollwheel, else false.
implementation
var PS2_Data_Mouse : sbit; sfr; external;
PS2_Clock_Mouse : sbit; sfr; external;
PS2_Data_Direction_Mouse : sbit; sfr; external;
PS2_Clock_Direction_Mouse : sbit; sfr; external;
TimeOut: word;
TimeOut2: word;
TimeOutError: boolean;
ScrollWheel: boolean;
function WaitForClockLow: boolean; // returns true if the clock went low within the TimeOut
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 0) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 0);
end;
function WaitForClockHigh: boolean; // returns true if the clock went high within the TimeOut
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 1) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 1);
end;
function WaitForInitialClockLow: boolean; // long timeout
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 0) or (TmpW >= TimeOut2);
Result := (PS2_Clock_Mouse = 0);
end;
function Ps2_Mouse_Get_Byte: byte;
// Reads one byte from the PS2 Mouse
var I, Tmp: byte;
begin
TimeOutError := false;
if not WaitForInitialClockLow then
begin
TimeOutError := true;
exit; // wait for first clockpulse with long timeout
end;
I := 0;
Tmp := 0;
while I < 11 do // 11 clockpulses expected
begin
if not WaitForClockLow then // wait for clock low (start of clockpulse)
begin
TimeOutError := true;
exit;
end;
if (I > 0) and (I < 9) then
begin
Tmp := Tmp Shr 1;
Tmp.7 := PS2_Data_Mouse;
end;
if not WaitForClockHigh then // wait for clock high (end of clockpulse)
begin
TimeOutError := true;
exit;
end;
inc(I);
end;
Result := tmp;
end;
function PS2_Mouse_SelftestResult: boolean;
var Tmp: byte;
Cnt: word;
begin
Result := false;
// wait for selftest completion
Cnt := 0;
repeat
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // release clock (allow Mouse to send)
nop; nop;
Tmp := Ps2_Mouse_Get_Byte;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock (do not allow Mouse to send)
nop; nop;
if not TimeOutError then // actual code received
begin
if Tmp = $AA
then Result := true // reset completion code (selftest done)
else if Tmp = $FC then exit; // error
end;
inc(Cnt);
until (Result = true) or (Cnt > 66); // 66 times 30 msecs is approx 2 secs
repeat // purge any extra bytes sent
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // release clock (allow Mouse to send)
nop; nop;
tmp := Ps2_Mouse_Get_Byte;
until TimeOutError;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock (do not allow Mouse to send)
nop; nop;
end;
function Ps2_Mouse_Enable_ScrollWheel: boolean;
var Cmd: array[7] of byte;
Tmp: byte;
begin
Result := false;
Cmd[0] := $F3; // Set Sample rate command
Cmd[1] := 200; // 200
Cmd[2] := $F3;
Cmd[3] := 100; // 100
Cmd[4] := $F3;
Cmd[5] := 80; // 80
Cmd[6] := $F2; // get ID byte
Ps2_Mouse_Write(Cmd, 7);
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1;
nop; nop;
Tmp := Ps2_Mouse_Get_Byte;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0;
nop; nop;
Result := (not TimeOutError) and (Tmp = 3);
end;
function Ps2_Mouse_ScrollWheel_Present: boolean;
begin
Result := ScrollWheel;
end;
function Ps2_Mouse_Reset: boolean;
var Arr: array[1] of byte;
begin
TimeOutError := false;
ScrollWheel := false;
Result := false;
Arr[0] := $FF; // reset command
Ps2_Mouse_Write(Arr, 1);
Result := PS2_Mouse_SelftestResult;
ScrollWheel := Ps2_Mouse_Enable_ScrollWheel;
Arr[0] := $F4;
Ps2_Mouse_Write(Arr, 1); // Enable Data Reporting
PS2_Clock_Mouse := 0; // force clock low (prevent mouse from sending data)
PS2_Clock_Direction_Mouse := 0;
nop; nop; // prevent read after write problem
end;
function Ps2_Mouse_Init: boolean;
// Initializes the Mouse Ps2 routines
begin
TimeOutError := false;
Result := false;
ScrollWheel := false;
TimeOut := DWord(11 * Clock_MHz); // gives approx 1 ms of timeout
TimeOut2 := 30 * TimeOut; // approx 30 ms
PS2_Clock_Mouse := 0; // force clock low
PS2_Clock_Direction_Mouse := 0;
nop; nop; // prevent read after write problem
PS2_Data_Mouse := 1;
PS2_Data_Direction_Mouse := 1;
nop; nop;
Result := PS2_Mouse_SelftestResult;
Result := Ps2_Mouse_Reset; // give extra reset
end;
function Ps2_Mouse_ReadData(var MouseData: TMouseData): boolean;
// Reads 3 or 4 bytes from the Ps2 Mouse into "MouseData"
var Index, Tmp: byte;
TmpCodes: array[4] of byte;
MaxCount: byte;
begin
Result := false;
TimeOutError := false;
Memset(@TmpCodes, 0, SizeOf(TmpCodes));
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // release clock (allow Mouse to send)
nop; nop;
// wait for first low clock with (short) timeout (low clock does not occur when no key is pressed: nothing to send)
if not WaitForClockLow then
begin
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
nop; nop;
exit; // no new data
end;
MaxCount := 3;
if ScrollWheel then MaxCount := 4;
Index := 0;
Repeat // get bytes until all bytes read
Tmp := Ps2_Mouse_Get_Byte;
if TimeOutError then
begin
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
nop; nop;
exit; // Read Error
end;
TmpCodes[Index] := Tmp;
inc(Index);
until Index = MaxCount;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock (prevent Mouse to send)
nop; nop;
MouseData.Keys := TmpCodes[0] and 7;
MouseData.DeltaX := 0;
if TmpCodes[0].4 = 1 then // X "sign" bit
MouseData.DeltaX := -1;
lo(MouseData.DeltaX) := TmpCodes[1];
MouseData.DeltaY := 0;
if TmpCodes[0].5 = 1 then // Y "sign" bit
MouseData.DeltaY := -1;
lo(MouseData.DeltaY) := TmpCodes[2];
MouseData.DeltaZ := 0;
if TmpCodes[3].7 = 1 then
MouseData.DeltaZ := -1;
lo(MouseData.DeltaZ) := TmpCodes[3];
Result := true;
end;
function WaitForClockHighThenLow: boolean;
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 1) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 1);
if not result then Exit;
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 0) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 0);
end;
function WaitForDataLowThenHigh: boolean;
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Data_Mouse = 0) or (TmpW >= TimeOut);
Result := (PS2_Data_Mouse = 0);
if not result then Exit;
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Data_Mouse = 1) or (TmpW >= TimeOut);
Result := (PS2_Data_Mouse = 1);
end;
procedure Ps2_Mouse_Write_Byte(Value: byte);
// writes 1 byte to the PS2 Mouse (command or data)
var parity, I: byte;
label ExitWriteByte;
begin
TimeOutError := false;
// calculate parity
Parity := 0;
for I := 0 to 7 do if Value.I = 0 then inc(Parity);
if Parity.0 = 1 // odd
then Parity := 0
else Parity := 1;
// make a request to send condition
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
delay_us(200);
PS2_Data_Mouse := 0; PS2_Data_Direction_Mouse := 0; // Make data line zero
nop; nop;
PS2_Clock_Direction_Mouse := 1; PS2_Clock_Mouse := 1; // release clock line
nop; nop;
if not WaitForInitialClockLow then
begin
TimeOutError := true;
goto ExitWriteByte;
end;
// send data and parity
for I := 0 to 8 do
begin
if I < 8 then
begin
PS2_Data_Mouse := Value.0; // send LSB bit
Value := Value shr 1; // get next bit
end
else PS2_Data_Mouse := Parity; // send parity
if not WaitForClockHighThenLow then
begin
TimeOutError := true;
goto ExitWriteByte;
end;
end;
PS2_Data_Mouse := 1; PS2_Data_Direction_Mouse := 1; // release dataline
if not WaitForClockHighThenLow then
begin
TimeOutError := true;
goto ExitWriteByte;
end;
if not WaitForDataLowThenHigh then // Check acknowledge (data line)
begin
TimeOutError := true;
goto ExitWriteByte;
end;
ExitWriteByte:
// done, release data and clock
PS2_Data_Direction_Mouse := 1; PS2_Data_Mouse := 1;
PS2_Clock_Direction_Mouse := 1; PS2_Clock_Mouse := 1;
end;
procedure Ps2_Mouse_Write(var Values: array[2] of byte; Count: byte);
// Writes "Count" bytes out of "Values" to the PS2 Mouse.
var Index, Reply: byte;
begin
Index := 0;
while Count > 0 do
begin
Ps2_Mouse_Write_Byte(Values[Index]); // send byte to the Mouse
if TimeOutError then break;
Reply := Ps2_Mouse_Get_Byte; // get the reply ($FA is Ok)
if TimeOutError then break;
inc(Index);
dec(Count);
end;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
nop; nop;
PS2_Data_Direction_Mouse := 1; PS2_Data_Mouse := 1; // release data line
nop; nop;
end;
procedure Ps2_Mouse_Write_Read(var Command: array[5] of byte; CountWrite: byte; var Reply: array[4] of byte; CountRead: byte);
var I: byte;
begin
Ps2_Mouse_Write(Command, CountWrite);
if CountRead > 0 then
begin
I := 0;
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // enable the mouse to send
nop; nop;
while I < CountRead do
begin
Reply[I] := Ps2_Mouse_Get_Byte;
inc(I);
end;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // disable the mouse to send
nop; nop;
end;
end;
end.
unit PS2_Mouse;
{interface }
type TMouseData =
record
Keys: byte;
DeltaX: integer;
DeltaY: integer;
DeltaZ: integer; // Scrollwheel
end;
function Ps2_Mouse_Init: boolean;
// Initializes the Mouse Ps2 library and resets the mouse.
// Returns true if a "Mouse selftest passed" code is received from the Mouse, else false.
// Also enables the ScrollWheel (if any present).
function Ps2_Mouse_ReadData(var MouseData: TMouseData): boolean;
// Reads the PS2 mouse data into "MouseData".
// MouseData.Keys returns the pressed keys (one bit for every key)
// MouseData.DeltaX returns the delta of the X value (hor position) with respect to the previous data
// MouseData.DeltaY returns the delta of the Y value (vert position) with respect to the previous data
// MouseData.DeltaZ returns the delta of the Scrollwheel value with respect to the previous data
procedure Ps2_Mouse_Write(var Values: array[2] of byte; Count: byte);
// Writes "Count" bytes out of "Values" to the PS2 Mouse. No reply expected here.
// The list of valid commands can be found in: http://www.computer-engineering.org/ps2mouse/
procedure Ps2_Mouse_Write_Read(var Command: array[5] of byte; CountWrite: byte; var Reply: array[4] of byte; CountRead: byte);
// Same as "Ps2_Mouse_Write" above, but after the write operation "CountRead" bytes are read from the mouse into "Reply".
function Ps2_Mouse_Reset: boolean;
// Resets the Mouse and waits (with a timeout of 2 seconds) for the "selftest passed" acknowledge.
// Returns true if the "selftest passed" was acknowledged by the Mouse, otherwise false.
// Remark: the Mouse also resets itself (and does a selftest) at power up time (see "Ps2_Mouse_Init").
function Ps2_Mouse_ScrollWheel_Present: boolean;
// Returns true if the mouse has a scrollwheel, else false.
implementation
var PS2_Data_Mouse : sbit; sfr; external;
PS2_Clock_Mouse : sbit; sfr; external;
PS2_Data_Direction_Mouse : sbit; sfr; external;
PS2_Clock_Direction_Mouse : sbit; sfr; external;
TimeOut: word;
TimeOut2: word;
TimeOutError: boolean;
ScrollWheel: boolean;
function WaitForClockLow: boolean; // returns true if the clock went low within the TimeOut
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 0) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 0);
end;
function WaitForClockHigh: boolean; // returns true if the clock went high within the TimeOut
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 1) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 1);
end;
function WaitForInitialClockLow: boolean; // long timeout
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 0) or (TmpW >= TimeOut2);
Result := (PS2_Clock_Mouse = 0);
end;
function Ps2_Mouse_Get_Byte: byte;
// Reads one byte from the PS2 Mouse
var I, Tmp: byte;
begin
TimeOutError := false;
if not WaitForInitialClockLow then
begin
TimeOutError := true;
exit; // wait for first clockpulse with long timeout
end;
I := 0;
Tmp := 0;
while I < 11 do // 11 clockpulses expected
begin
if not WaitForClockLow then // wait for clock low (start of clockpulse)
begin
TimeOutError := true;
exit;
end;
if (I > 0) and (I < 9) then
begin
Tmp := Tmp Shr 1;
Tmp.7 := PS2_Data_Mouse;
end;
if not WaitForClockHigh then // wait for clock high (end of clockpulse)
begin
TimeOutError := true;
exit;
end;
inc(I);
end;
Result := tmp;
end;
function PS2_Mouse_SelftestResult: boolean;
var Tmp: byte;
Cnt: word;
begin
Result := false;
// wait for selftest completion
Cnt := 0;
repeat
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // release clock (allow Mouse to send)
nop; nop;
Tmp := Ps2_Mouse_Get_Byte;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock (do not allow Mouse to send)
nop; nop;
if not TimeOutError then // actual code received
begin
if Tmp = $AA
then Result := true // reset completion code (selftest done)
else if Tmp = $FC then exit; // error
end;
inc(Cnt);
until (Result = true) or (Cnt > 66); // 66 times 30 msecs is approx 2 secs
repeat // purge any extra bytes sent
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // release clock (allow Mouse to send)
nop; nop;
tmp := Ps2_Mouse_Get_Byte;
until TimeOutError;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock (do not allow Mouse to send)
nop; nop;
end;
function Ps2_Mouse_Enable_ScrollWheel: boolean;
var Cmd: array[7] of byte;
Tmp: byte;
begin
Result := false;
Cmd[0] := $F3; // Set Sample rate command
Cmd[1] := 200; // 200
Cmd[2] := $F3;
Cmd[3] := 100; // 100
Cmd[4] := $F3;
Cmd[5] := 80; // 80
Cmd[6] := $F2; // get ID byte
Ps2_Mouse_Write(Cmd, 7);
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1;
nop; nop;
Tmp := Ps2_Mouse_Get_Byte;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0;
nop; nop;
Result := (not TimeOutError) and (Tmp = 3);
end;
function Ps2_Mouse_ScrollWheel_Present: boolean;
begin
Result := ScrollWheel;
end;
function Ps2_Mouse_Reset: boolean;
var Arr: array[1] of byte;
begin
TimeOutError := false;
ScrollWheel := false;
Result := false;
Arr[0] := $FF; // reset command
Ps2_Mouse_Write(Arr, 1);
Result := PS2_Mouse_SelftestResult;
ScrollWheel := Ps2_Mouse_Enable_ScrollWheel;
Arr[0] := $F4;
Ps2_Mouse_Write(Arr, 1); // Enable Data Reporting
PS2_Clock_Mouse := 0; // force clock low (prevent mouse from sending data)
PS2_Clock_Direction_Mouse := 0;
nop; nop; // prevent read after write problem
end;
function Ps2_Mouse_Init: boolean;
// Initializes the Mouse Ps2 routines
begin
TimeOutError := false;
Result := false;
ScrollWheel := false;
TimeOut := DWord(11 * Clock_MHz); // gives approx 1 ms of timeout
TimeOut2 := 30 * TimeOut; // approx 30 ms
PS2_Clock_Mouse := 0; // force clock low
PS2_Clock_Direction_Mouse := 0;
nop; nop; // prevent read after write problem
PS2_Data_Mouse := 1;
PS2_Data_Direction_Mouse := 1;
nop; nop;
Result := PS2_Mouse_SelftestResult;
Result := Ps2_Mouse_Reset; // give extra reset
end;
function Ps2_Mouse_ReadData(var MouseData: TMouseData): boolean;
// Reads 3 or 4 bytes from the Ps2 Mouse into "MouseData"
var Index, Tmp: byte;
TmpCodes: array[4] of byte;
MaxCount: byte;
begin
Result := false;
TimeOutError := false;
Memset(@TmpCodes, 0, SizeOf(TmpCodes));
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // release clock (allow Mouse to send)
nop; nop;
// wait for first low clock with (short) timeout (low clock does not occur when no key is pressed: nothing to send)
if not WaitForClockLow then
begin
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
nop; nop;
exit; // no new data
end;
MaxCount := 3;
if ScrollWheel then MaxCount := 4;
Index := 0;
Repeat // get bytes until all bytes read
Tmp := Ps2_Mouse_Get_Byte;
if TimeOutError then
begin
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
nop; nop;
exit; // Read Error
end;
TmpCodes[Index] := Tmp;
inc(Index);
until Index = MaxCount;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock (prevent Mouse to send)
nop; nop;
MouseData.Keys := TmpCodes[0] and 7;
MouseData.DeltaX := 0;
if TmpCodes[0].4 = 1 then // X "sign" bit
MouseData.DeltaX := -1;
lo(MouseData.DeltaX) := TmpCodes[1];
MouseData.DeltaY := 0;
if TmpCodes[0].5 = 1 then // Y "sign" bit
MouseData.DeltaY := -1;
lo(MouseData.DeltaY) := TmpCodes[2];
MouseData.DeltaZ := 0;
if TmpCodes[3].7 = 1 then
MouseData.DeltaZ := -1;
lo(MouseData.DeltaZ) := TmpCodes[3];
Result := true;
end;
function WaitForClockHighThenLow: boolean;
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 1) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 1);
if not result then Exit;
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Clock_Mouse = 0) or (TmpW >= TimeOut);
Result := (PS2_Clock_Mouse = 0);
end;
function WaitForDataLowThenHigh: boolean;
var TmpW: word;
begin
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Data_Mouse = 0) or (TmpW >= TimeOut);
Result := (PS2_Data_Mouse = 0);
if not result then Exit;
TmpW := 0;
repeat
inc(TmpW);
until (PS2_Data_Mouse = 1) or (TmpW >= TimeOut);
Result := (PS2_Data_Mouse = 1);
end;
procedure Ps2_Mouse_Write_Byte(Value: byte);
// writes 1 byte to the PS2 Mouse (command or data)
var parity, I: byte;
label ExitWriteByte;
begin
TimeOutError := false;
// calculate parity
Parity := 0;
for I := 0 to 7 do if Value.I = 0 then inc(Parity);
if Parity.0 = 1 // odd
then Parity := 0
else Parity := 1;
// make a request to send condition
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
delay_us(200);
PS2_Data_Mouse := 0; PS2_Data_Direction_Mouse := 0; // Make data line zero
nop; nop;
PS2_Clock_Direction_Mouse := 1; PS2_Clock_Mouse := 1; // release clock line
nop; nop;
if not WaitForInitialClockLow then
begin
TimeOutError := true;
goto ExitWriteByte;
end;
// send data and parity
for I := 0 to 8 do
begin
if I < 8 then
begin
PS2_Data_Mouse := Value.0; // send LSB bit
Value := Value shr 1; // get next bit
end
else PS2_Data_Mouse := Parity; // send parity
if not WaitForClockHighThenLow then
begin
TimeOutError := true;
goto ExitWriteByte;
end;
end;
PS2_Data_Mouse := 1; PS2_Data_Direction_Mouse := 1; // release dataline
if not WaitForClockHighThenLow then
begin
TimeOutError := true;
goto ExitWriteByte;
end;
if not WaitForDataLowThenHigh then // Check acknowledge (data line)
begin
TimeOutError := true;
goto ExitWriteByte;
end;
ExitWriteByte:
// done, release data and clock
PS2_Data_Direction_Mouse := 1; PS2_Data_Mouse := 1;
PS2_Clock_Direction_Mouse := 1; PS2_Clock_Mouse := 1;
end;
procedure Ps2_Mouse_Write(var Values: array[2] of byte; Count: byte);
// Writes "Count" bytes out of "Values" to the PS2 Mouse.
var Index, Reply: byte;
begin
Index := 0;
while Count > 0 do
begin
Ps2_Mouse_Write_Byte(Values[Index]); // send byte to the Mouse
if TimeOutError then break;
Reply := Ps2_Mouse_Get_Byte; // get the reply ($FA is Ok)
if TimeOutError then break;
inc(Index);
dec(Count);
end;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // block clock
nop; nop;
PS2_Data_Direction_Mouse := 1; PS2_Data_Mouse := 1; // release data line
nop; nop;
end;
procedure Ps2_Mouse_Write_Read(var Command: array[5] of byte; CountWrite: byte; var Reply: array[4] of byte; CountRead: byte);
var I: byte;
begin
Ps2_Mouse_Write(Command, CountWrite);
if CountRead > 0 then
begin
I := 0;
PS2_Clock_Mouse := 1; PS2_Clock_Direction_Mouse := 1; // enable the mouse to send
nop; nop;
while I < CountRead do
begin
Reply[I] := Ps2_Mouse_Get_Byte;
inc(I);
end;
PS2_Clock_Mouse := 0; PS2_Clock_Direction_Mouse := 0; // disable the mouse to send
nop; nop;
end;
end;
end.