How to interface a Hantick PS/2 touchpad with Arduino. Use it to crossfade a bicolor LED.

Some while ago, I found a Processing example that would crossfade an Arduino connected bicolor LED depending on mouse position over a window with a gradient. Since I had a touchpad from an old netbook, I decided to use a hardware approach: interface this to Arduino and use it to change LED color by swiping left or right. Horizontal swiping will change the duty factor of PWM signals that light the LED.

This is a simple project that can be built with other kind of input devices like potentiometer or joystick. But, my purpose was to get that touchpad working. I had to use a logic analyzer to determine its pinout. Luckily, since it uses PS/2 protocol, it sends some bytes without connection to a host device. The PS/2 protocol is well documented and pretty easy. ATmega microcontrollers used by Arduino boards don't have hardware support for this protocol, therefore it must be implemented in software. Some searching revealed a lot of libraries for PS/2 devices, but not all worked for me. This may be because the touchpad I used is pretty old and may not support all protocol features.

The touchpad I used is Hantick HTX5330M. I could not find a datasheet for it or for the IC it uses. It connects to motherboard by a 6 wire ribbon cable. Identifying power and ground lines is easy (most PCBs use GND as a plane and between this and VCC there are large capacitors). A closer look near the motherboard connector, shows two pull-up resistors of 7.5k.

The red and black dots represent the power lines. And it seems there are only tow signal lines, the ones that are pulled up. The manufacturer provided two test points (TP9 and TP10) for these lines. That's where I connected the logic analyzer. It looks like TP9 is PS/2 DATA and TP10 is PS/2 CLOCK. The device uses 5V levels. In the top photo, you see I cut this part of the motherboard because I wanted to keep the connector and the rather unusual pull-ups of 7.5k.

I managed to find a specification page for this device. This confirmed 5V usage and PS/2 compatibility of the 48 by 32.5mm device. I can proceed and connect this to an Arduino compatible board. Since many PS/2 projects I could find used Arduino pins 5 and 6 I did the same. Pin D6 goes to TP10 (clock) and pin D5 to TP9 (data). 5V are also supplied by Arduino (the touchpad draws about 3mA).

 Connect the touchpad and LED to Arduino
Let's get to the software. PS/2 is a bidirectional synchronous serial protocol (see The PS/2 Mouse/Keyboard Protocol by Adam Chapweske). When the host device keeps bus idle, the touchpad generates clock and send data to the host. Clock is always generated by PS/2 device, not the host. When the host needs to send data, it generates a request state and waits the clock from the PS/2 device. Mouse and touchpad have specific commands and three working modes. The host can tell the touchpad to send data as soon as it receives (stream mode) or it can poll the device frequently for data (remote mode). The third mode is wrap mode, where the device echoes data received from the host. Computers equipped with PS/2 input devices prefer to use stream mode (read more about The PS/2 Mouse Interface by Adam Chapweske).

The Arduino library that worked best for me is written by Jacek Kunicki and can be donwloaded from GitHub. It works in remote mode (it polls mouse/touchpad for new data every 20ms). Using this library, the code becomes very simple. Here is the Arduino sketch.
#include "PS2Mouse.h"
#define DATA_PIN 5
#define CLOCK_PIN 6

PS2Mouse mouse(CLOCK_PIN, DATA_PIN);

int red, green;

void setup() {
Serial.begin(9600);
Serial.println("Using PS/2 librray by Jacek Kunicki (https://github.com/rucek)");

pinMode(9, OUTPUT);
pinMode(10, OUTPUT);

red = 127; green = 127;

analogWrite(9, red);
analogWrite(10, green);

mouse.initialize();
}

void loop() {
red += data.position.x;
green -= data.position.x;

if (red > 255) red = 255; if (red < 0) red = 0;
if (green > 255) green = 255; if (green < 0) green = 0;

analogWrite(9, red);
analogWrite(10, green);

delay(20);
}

The LED is connected to PWM pins. The start-up duty cycle is 50% (127 is nearly half of 255). Only X axis is read and used to modify PWM duty cycle. The movement on X axis generates a relative value, which is positive for right swiping and negative for left swiping. This value is added to one of the LEDs and subtracted from the other. If it's positive, it will increase duty cycle of PWM signal that controls the LED to which is added and decrease the duty where it is subtracted. If it's negative, the opposite happens.