CDL Modules
Data Structures | Namespaces | Enumerations | Variables
ps2_host.cdl File Reference

PS2 interface for keyboard or mouse. More...

Detailed Description

PS2 interface for keyboard or mouse.

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

  1. Pull data low; wait 5us to 25us.
  2. Pull clock low; wait 30us.
  3. Let clock rise; wait 15us.
  4. Pull data low or let it rise; wait 15us (data bit 0)
  5. Pull clock low; wait 30us.
  6. 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:

  1. Pull clock low for 100us; start 15ms timeout
  2. Pull data low, wait for 15us.
  3. Let clock rise, wait for 15us.
  4. Check the clock is high.
  5. Wait for clock low
  6. On clock low, wait for 10us, and set data to data bit 0
  7. Wait for clock high
  8. 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
  9. On clock low, wait for 10us, and set data to parity bit
  10. Wait for clock high
  11. Wait for clock low
  12. On clock low, wait for 10us, let data rise (stop bit)
  13. Wait for clock high
  14. Wait for clock low
  15. 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:

  1. Look for clock falling
  2. If data is low, then assume this is a start bit. Set timeout timer.
  3. Wait for clock falling. Clock in data bit 0
  4. Wait for clock falling. Clock in data bit 1
  5. Wait for clock falling. Clock in data bit 2
  6. Wait for clock falling. Clock in data bit 3
  7. Wait for clock falling. Clock in data bit 4
  8. Wait for clock falling. Clock in data bit 5
  9. Wait for clock falling. Clock in data bit 6
  10. Wait for clock falling. Clock in data bit 7
  11. Wait for clock falling. Clock in parity bit.
  12. Wait for clock falling. Clock in stop bit.
  13. Wait for clock high.
  14. Validate data (stop bit 1, parity correct)

Data Structures

struct  ps2_host::t_clock_state
 
struct  ps2_host::t_clock_combs
 
struct  ps2_host::t_ps2_input_state
 
struct  ps2_host::t_ps2_input_combs
 
struct  ps2_host::t_rx_result
 
struct  ps2_host::t_ps2_receive_state
 
struct  ps2_host::t_ps2_receive_combs
 

Namespaces

 ps2_host
 

Enumerations

enum  ps2_host::t_rx_action {
  ps2_host::action_rx_none,
  ps2_host::action_rx_start,
  ps2_host::action_rx_clock_finishing_data,
  ps2_host::action_rx_clock_rising_in_bit,
  ps2_host::action_rx_clock_data,
  ps2_host::action_rx_acknowledge_timeout,
  ps2_host::action_rx_acknowledge_error,
  ps2_host::action_rx_error,
  ps2_host::action_rx_timeout
}
 
enum  ps2_host::t_receive_fsm {
  ps2_host::receive_fsm_idle,
  ps2_host::receive_fsm_data_bit_clock_low,
  ps2_host::receive_fsm_data_bit_clock_high,
  ps2_host::receive_fsm_error,
  ps2_host::receive_fsm_timeout
}
 

Variables

constant integer ps2_host::timeout_rx_data =1000