Trackpad

Intro

The trackpad is another Shenzhen e-waste find. These leftover 8520 trackpads fit perfectly into the 9700 keypad and with a bit of help from some Arduino forums, we were able to hobble together some functioning trackpad code. It turns out, this device is relatively easy to communicate with over SPI. The devices returns changes in x and y coordinates when the user swipes across the surface of the device. We've included some code that conveniently converts this data into a clean 'swipe right' or 'swipe left' when an event is detected.

Trackpad hardware

The trackpad is from the Blackberry 8250. It's likely to have some version of the Agilent ADNS-3060 sensor inside of it commonly used for optical mice. A flexible PCB breakouts out to a 20 pin Hirose connector, which have designed into our PCB.

Working with the Screen

Heads Up!

The trackpad runs at 3.3 volts, so we have added the TXB0104 level shifter from the AtMega 2560 mcu to handle high speed bi-directional data. In order to transmit SPI data correction, remember to set the TXB0104's OE pin low upon startup, and then set the pin high to enable level shifted SPI communication.

!

The RFM95 radio, screen, and microSD card slot are also connected to the level shifter SPI lines, so remember to set these devices' chip select pins accordingly to ensure they do not interfere with your screen communication.

After you've verified the notes above, you can get started handling data from the trackpad. We suggest starting with the basic code snippets that we have included below. How far you want to take it is up to you as this is by the far the most complicated and least documented device in the design.

Trackpad library

Currently there is no library written for the trackpad we use (but let us know if you come across one). As of now, we can access the registers of the trackpad chip using the Arduino SPI library.

We can define two basic functions to read from and write to the trackpad CPU register. See code snippet below.

Trackpad example code

#include <SPI.h>

#define TP_RESET     25
#define TP_SHUTDOWN  24
#define TP_CS        47
#define TP_BUTTON    23
#define SD_CS        22
#define TFT_CS       27
#define RFM_CS       10
#define LVL_SHIFT_EN  2

void setup() {
  pinMode(TP_SHUTDOWN, OUTPUT);
  pinMode(TP_RESET, OUTPUT);
  pinMode(TP_CS, OUTPUT);
  pinMode(TP_BUTTON, INPUT);
  pinMode(LVL_SHIFT_EN, OUTPUT);

  // Turn off other SPI
  // TODO: confirm if we really need to do this o-O
  digitalWrite(SD_CS, HIGH);
  digitalWrite(TFT_CS, HIGH);
  digitalWrite(RFM_CS, HIGH);

  digitalWrite(LVL_SHIFT_EN, LOW);
  delay(1000);
  digitalWrite(LVL_SHIFT_EN, HIGH);

  // ADNS-3060 does not perform an internal power up self-reset
  // Force a reset
  digitalWrite(TP_RESET, HIGH);
  delay(1000);
  digitalWrite(TP_RESET, LOW);

  digitalWrite(TP_SHUTDOWN, LOW);
  // Ensure trackpad is not listening
  digitalWrite(TP_CS, HIGH);

  SPI.begin();

  // Wait for serial monitor to open before we continue setup
  Serial.begin(115200);
  while (!Serial);

  Serial.print("Product ID: ");

  writeRegister(0x00, 0x00);
  uint8_t productID = readRegister(0x00);
  Serial.println(productID);
}

uint8_t motion = 0;

void loop() {
  motion = readRegister(0x02);

  // Motion has occurred on the trackpad
  if (motion > 127) {
    int8_t dx = readRegister(0x03);
    int8_t dy = readRegister(0x04);
    Serial.print("x: ");
    Serial.println(dx);
    Serial.print("y: ");
    Serial.println(dy);
  }
}

byte readRegister(uint8_t address) {
  byte data;
  // Make trackpad listen
  digitalWrite(TP_CS, LOW);

  // Write the address of the register we want to read from
  // Most significant byte should be 0 here to indicate read operation
  SPI.transfer(address);

  // Read the data
  data = SPI.transfer(0x00);
  delayMicroseconds(50);

  // Make trackpad stop listening
  digitalWrite(TP_CS, HIGH);

  return data;
}

void writeRegister(uint8_t address, uint8_t data) {
  // Set most significant byte high to indicate write operation
  address |= 0x80;
  digitalWrite(TP_CS, LOW);

  // Send the address of the register we want to write to
  SPI.transfer(address);

  // Write data to register
  SPI.transfer(data);
  delayMicroseconds(50);

  // Make trackpad stop listening
  digitalWrite(TP_CS, HIGH);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

Arduino SPI Library

Agilent ADNS-3060 Datasheet

Last Updated: 6/26/2018, 2:41:14 PM