AppleIIMouse/Arduino/PS2Mouse.cpp

157 lines
3.3 KiB
C++

#include "Arduino.h"
#include "HardwareSerial.h"
#include "PS2Mouse.h"
PS2Mouse::PS2Mouse(int data_pin, int clock_pin)
{
_data_pin = data_pin;
_clock_pin = clock_pin;
}
/*
* according to some code I saw, these functions will
* correctly set the mouse clock and data pins for
* various conditions.
*/
void PS2Mouse::gohi(int pin)
{
pinMode(pin, INPUT);
digitalWrite(pin, HIGH);
}
void PS2Mouse::golo(int pin)
{
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
void PS2Mouse::write(char data)
{
char i;
char parity = 1;
// Serial.print("Sending ");
// Serial.print(data, HEX);
// Serial.print(" to mouse\n");
// Serial.print("RTS");
/* put pins in output mode */
gohi(_data_pin);
gohi(_clock_pin);
delayMicroseconds(300);
golo(_clock_pin);
delayMicroseconds(300);
golo(_data_pin);
delayMicroseconds(10);
/* start bit */
gohi(_clock_pin);
/* wait for mouse to take control of clock); */
while (digitalRead(_clock_pin) == HIGH)
;
/* clock is low, and we are clear to send data */
for (i=0; i < 8; i++) {
if (data & 0x01) {
gohi(_data_pin);
}
else {
golo(_data_pin);
}
/* wait for clock cycle */
while (digitalRead(_clock_pin) == LOW)
;
while (digitalRead(_clock_pin) == HIGH)
;
parity = parity ^ (data & 0x01);
data = data >> 1;
}
/* parity */
if (parity) {
gohi(_data_pin);
}
else {
golo(_data_pin);
}
while (digitalRead(_clock_pin) == LOW)
;
while (digitalRead(_clock_pin) == HIGH)
;
/* stop bit */
gohi(_data_pin);
delayMicroseconds(50);
while (digitalRead(_clock_pin) == HIGH)
;
/* wait for mouse to switch modes */
while ((digitalRead(_clock_pin) == LOW) || (digitalRead(_data_pin) == LOW))
;
/* put a hold on the incoming data. */
golo(_clock_pin);
// Serial.print("done.\n");
}
/*
* Get a byte of data from the mouse
*/
char PS2Mouse::read(void)
{
char data = 0x00;
int i;
char bit = 0x01;
// Serial.print("reading byte from mouse\n");
/* start the clock */
gohi(_clock_pin);
gohi(_data_pin);
delayMicroseconds(50);
while (digitalRead(_clock_pin) == HIGH)
;
delayMicroseconds(5); /* not sure why */
while (digitalRead(_clock_pin) == LOW) /* eat start bit */
;
for (i=0; i < 8; i++) {
while (digitalRead(_clock_pin) == HIGH)
;
if (digitalRead(_data_pin) == HIGH) {
data = data | bit;
}
while (digitalRead(_clock_pin) == LOW)
;
bit = bit << 1;
}
/* eat parity bit, which we ignore */
while (digitalRead(_clock_pin) == HIGH)
;
while (digitalRead(_clock_pin) == LOW)
;
/* eat stop bit */
while (digitalRead(_clock_pin) == HIGH)
;
while (digitalRead(_clock_pin) == LOW)
;
/* put a hold on the incoming data. */
golo(_clock_pin);
// Serial.print("Recvd data ");
// Serial.print(data, HEX);
// Serial.print(" from mouse\n");
return data;
}
void PS2Mouse::init()
{
gohi(_clock_pin);
gohi(_data_pin);
// Serial.print("Sending reset to mouse\n");
write(0xff);
read(); /* ack byte */
// Serial.print("Read ack byte1\n");
read(); /* blank */
read(); /* blank */
// Serial.print("Sending remote mode code\n");
write(0xf0); /* remote mode */
read(); /* ack */
// Serial.print("Read ack byte2\n");
delayMicroseconds(100);
}