Skip to content

Commit

Permalink
A few addition to PS2 documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi committed Nov 26, 2016
1 parent bf23ac9 commit f837406
Showing 1 changed file with 125 additions and 35 deletions.
160 changes: 125 additions & 35 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1160,41 +1160,131 @@ Please note the USB port can only supply a limited amount of power to the keyboa
## PS/2 Mouse Support

Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device.
In order to do this you must first enable the option in your Makefile.

PS2_MOUSE_ENABLE = yes

Then, decide whether to use interrupts (better if your microcontroller supports them) or busywait, and enable the relevant option.

PS2_USE_INT = yes
// PS2_USE_BUSYWAIT = yes

If you're using a teensy and have hooked up the clock on your PS/2 device to D1 and the data to D0, you're all set.
Otherwise, you will need to update the following defines in your `config.h`:

#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1

#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0

And with `PS2_USE_INT` also define these macros:

#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC11) | \
(0<<ISC10)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT1); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT1); \
} while (0)
#define PS2_INT_VECT INT1_vect

Then, decide whether to use USART (best), interrupts (better) or busywait (not recommended), and enable the relevant option.

### Busywait version

Note: This is not recommended, you may encounter jerky movement or unsent inputs. Please use interrupt or USART version if possible.

In rules.mk:

```
PS2_MOUSE_ENABLE = yes
PS2_USE_BUSYWAIT = yes
```

In your keyboard config.h:

```
#ifdef PS2_USE_BUSYWAIT
# define PS2_CLOCK_PORT PORTD
# define PS2_CLOCK_PIN PIND
# define PS2_CLOCK_DDR DDRD
# define PS2_CLOCK_BIT 1
# define PS2_DATA_PORT PORTD
# define PS2_DATA_PIN PIND
# define PS2_DATA_DDR DDRD
# define PS2_DATA_BIT 2
#endif
```

### Interrupt version

The following example uses D2 for clock and D5 for data. You can use any INT or PCINT pin for clock, and any pin for data.

In rules.mk:

```
PS2_MOUSE_ENABLE = yes
PS2_USE_INT = yes
```

In your keyboard config.h:

```
#ifdef PS2_USE_INT
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 2
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 5
#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC21) | \
(0<<ISC20)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT2); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT2); \
} while (0)
#define PS2_INT_VECT INT2_vect
#endif
```

### USART version

To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version.

In rules.mk:

```
PS2_MOUSE_ENABLE = yes
PS2_USE_USART = yes
```

In your keyboard config.h:

```
#ifdef PS2_USE_USART
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 5
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 2
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
/* set DDR of CLOCK as input to be slave */
#define PS2_USART_INIT() do { \
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
UCSR1C = ((1 << UMSEL10) | \
(3 << UPM10) | \
(0 << USBS1) | \
(3 << UCSZ10) | \
(0 << UCPOL1)); \
UCSR1A = 0; \
UBRR1H = 0; \
UBRR1L = 0; \
} while (0)
#define PS2_USART_RX_INT_ON() do { \
UCSR1B = ((1 << RXCIE1) | \
(1 << RXEN1)); \
} while (0)
#define PS2_USART_RX_POLL_ON() do { \
UCSR1B = (1 << RXEN1); \
} while (0)
#define PS2_USART_OFF() do { \
UCSR1C = 0; \
UCSR1B &= ~((1 << RXEN1) | \
(1 << TXEN1)); \
} while (0)
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1))
#define PS2_USART_RX_DATA UDR1
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
#define PS2_USART_RX_VECT USART1_RX_vect
#endif
#endif
#endif
```

## Safety Considerations

Expand Down

0 comments on commit f837406

Please sign in to comment.