PS2 interface for keyboard or mouse.
- Copyright
- (C) 2016-2017, Gavin J Stark. All rights reserved.
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
CDL implementation of a PS2 interface host driver
The PS/2 interface is a bidirectional serial interface running on an open collector bus pin pair (clock and data).
A slave, such as a keyboard or mouse, owns the pin, except for the one time that a host can usurp it to request transfer from host to slave. (Known as clock-inhibit)
A slave can present data to the host (this module) by:
0. Ensure clock is high for 50us
- Pull data low; wait 5us to 25us.
- Pull clock low; wait 30us.
- Let clock rise; wait 15us.
- Pull data low or let it rise; wait 15us (data bit 0)
- Pull clock low; wait 30us.
- Let clock rise; wait 15us. 7... Pull data low or let it rise; wait 15us (data bit 1..7) 8... Pull clock low; wait 30us 9... Let clock rise; wait 15us - repeat from 7 10... Pull data low or let it rise; wait 15us (parity bit) 11... Pull clock low; wait 30us 12... Let clock rise; wait 15us. 13... Let data rise; wait 15us (stop bit) 14... Pull clock low; wait 30us 15... Let clock rise; wait 15us.
If the clock fails to rise on any of the pulses - because the host is driving it low (clock-inhibit) - the slave will have to retransmit the byte (and any other byte of a packet that it has already sent).
A host can present data to the slave with:
- Pull clock low for 100us; start 15ms timeout
- Pull data low, wait for 15us.
- Let clock rise, wait for 15us.
- Check the clock is high.
- Wait for clock low
- On clock low, wait for 10us, and set data to data bit 0
- Wait for clock high
- Wait for clock low 9... On clock low, wait for 10us, and set data to data bit 1..7 10... Wait for clock high 11... Wait for clock low
- On clock low, wait for 10us, and set data to parity bit
- Wait for clock high
- Wait for clock low
- On clock low, wait for 10us, let data rise (stop bit)
- Wait for clock high
- Wait for clock low
- Wait for 10us, check that data is low (ack)
A strategy is to run at (for example) ~3us per 'tick', and use that to look for valid data streams on the pins.
As a host, to receive data from the slave (the first target for the design), we have to:
- Look for clock falling
- If data is low, then assume this is a start bit. Set timeout timer.
- Wait for clock falling. Clock in data bit 0
- Wait for clock falling. Clock in data bit 1
- Wait for clock falling. Clock in data bit 2
- Wait for clock falling. Clock in data bit 3
- Wait for clock falling. Clock in data bit 4
- Wait for clock falling. Clock in data bit 5
- Wait for clock falling. Clock in data bit 6
- Wait for clock falling. Clock in data bit 7
- Wait for clock falling. Clock in parity bit.
- Wait for clock falling. Clock in stop bit.
- Wait for clock high.
- Validate data (stop bit 1, parity correct)