Merge branch 'master' of mjesec.ffzg.hr:/git/Arduino
[Arduino] / libraries / ps2dev / ps2dev.cpp
1 /*
2  * ps2dev.cpp - an interface library for ps2 host.  
3  * limitations:
4  *      we do not handle parity errors.
5  *      The timing constants are hard coded from the spec. Data rate is
6  *         not impressive.
7  *      probably lots of room for optimization.
8  */
9
10 #include "WProgram.h"
11 #include "ps2dev.h"
12
13
14 //since for the device side we are going to be in charge of the clock,
15 //the two defines below are how long each _phase_ of the clock cycle is
16 #define CLKFULL 40
17 // we make changes in the middle of a phase, this how long from the
18 // start of phase to the when we drive the data line
19 #define CLKHALF 20
20
21 /*
22  * the clock and data pins can be wired directly to the clk and data pins
23  * of the PS2 connector.  No external parts are needed.
24  */
25 PS2dev::PS2dev(int clk, int data)
26 {
27   _ps2clk = clk;
28   _ps2data = data;
29   gohi(_ps2clk);
30   gohi(_ps2data);
31 }
32
33 /*
34  * according to some code I saw, these functions will
35  * correctly set the clock and data pins for
36  * various conditions.  It's done this way so you don't need
37  * pullup resistors.
38  */
39 void
40 PS2dev::gohi(int pin)
41 {
42   pinMode(pin, INPUT);
43   digitalWrite(pin, HIGH);
44 }
45
46 void
47 PS2dev::golo(int pin)
48 {
49   pinMode(pin, OUTPUT);
50   digitalWrite(pin, LOW);
51 }
52
53 int PS2dev::write(unsigned char data)
54 {
55   unsigned char i;
56   unsigned char parity = 1;
57
58   //    Serial.print("sending ");
59   //Serial.println(data,HEX);
60
61         
62   if (digitalRead(_ps2clk) == LOW) {
63     return -1;
64   }
65
66   if (digitalRead(_ps2data) == LOW) {
67     return -2;
68   }
69
70
71   golo(_ps2data);
72   delayMicroseconds(CLKHALF);
73   // device sends on falling clock
74   golo(_ps2clk);        // start bit
75   delayMicroseconds(CLKFULL);
76   gohi(_ps2clk);
77   delayMicroseconds(CLKHALF);
78
79   for (i=0; i < 8; i++)
80     {
81       if (data & 0x01)
82         {
83           gohi(_ps2data);
84         } else {
85         golo(_ps2data);
86       }
87       delayMicroseconds(CLKHALF);
88       golo(_ps2clk);    
89       delayMicroseconds(CLKFULL);
90       gohi(_ps2clk);
91       delayMicroseconds(CLKHALF);
92
93       parity = parity ^ (data & 0x01);
94       data = data >> 1;
95     }
96   // parity bit
97   if (parity)
98     {
99       gohi(_ps2data);
100     } else {
101     golo(_ps2data);
102   }
103   delayMicroseconds(CLKHALF);
104   golo(_ps2clk);        
105   delayMicroseconds(CLKFULL);
106   gohi(_ps2clk);
107   delayMicroseconds(CLKHALF);
108
109   // stop bit
110   gohi(_ps2data);
111   delayMicroseconds(CLKHALF);
112   golo(_ps2clk);        
113   delayMicroseconds(CLKFULL);
114   gohi(_ps2clk);
115   delayMicroseconds(CLKHALF);
116
117   delayMicroseconds(50);
118   return 0;
119 }
120
121
122 int PS2dev::read(unsigned char * value)
123 {
124   unsigned char data = 0x00;
125   unsigned char i;
126   unsigned char bit = 0x01;
127   
128   unsigned char parity = 1;
129   
130   //wait for data line to go low
131   while (digitalRead(_ps2data) == HIGH) {
132
133   } 
134   //wait for clock line to go high
135   while (digitalRead(_ps2clk) == LOW) {
136
137   } 
138
139   
140   delayMicroseconds(CLKHALF);
141   golo(_ps2clk);
142   delayMicroseconds(CLKFULL);
143   gohi(_ps2clk);
144   delayMicroseconds(CLKHALF);
145
146   for (i=0; i < 8; i++)
147     {
148       if (digitalRead(_ps2data) == HIGH)
149         {
150           data = data | bit;
151         } else {
152       }
153
154
155       bit = bit << 1;
156       
157       delayMicroseconds(CLKHALF);
158       golo(_ps2clk);    
159       delayMicroseconds(CLKFULL);
160       gohi(_ps2clk);
161       delayMicroseconds(CLKHALF);
162       
163       parity = parity ^ (data & 0x01);
164     }
165   // we do the delay at the end of the loop, so at this point we have
166   // already done the delay for the parity bit
167
168   // stop bit
169   delayMicroseconds(CLKHALF);
170   golo(_ps2clk);        
171   delayMicroseconds(CLKFULL);
172   gohi(_ps2clk);
173   delayMicroseconds(CLKHALF);
174   
175
176   delayMicroseconds(CLKHALF);
177   golo(_ps2data);
178   golo(_ps2clk);        
179   delayMicroseconds(CLKFULL);
180   gohi(_ps2clk);
181   delayMicroseconds(CLKHALF);
182   gohi(_ps2data);
183
184
185   *value = data;
186   
187   return 0;
188 }
189
190