AD7879

AD7879 Input Touch Screen Digitizer Linux Driver.

Supported Devices

Evaluation Boards

Description

The AD7879/AD7889 is a 12-bit successive approximation ADC with a synchronous serial interface and low on-resistance switches for driving 4-wire resistive touch screens. The AD7879 works with a very low power supply, a single 1.6 V to 3.6V, and features throughput rates of 105 kSPS.

The device includes a low-power shutdown mode.

To reduce the effects of noise from LCDs and other sources, the AD7879 contains a preprocessing block. The preprocessing function consists of a median and an averaging filter. The combination of these two techniques provides a more robust solution, discarding the spurious noise in the signal and keeping only the data of interest. The size of both filters is programmable. Other user-programmable conversion controls include variable acquisition time, and first conversion delay. Up to 16 averages can be taken per conversion. The AD7879 can run in either slave or stand-alone mode, using an automatic conversion sequencer and timer.

https://wiki.analog.com/_media/software/driver/linux/ad7879_filter_example.png

The AD7879 has a programmable pin that can operate as either an auxiliary input to the ADC, as a battery monitor, or as a GPIO. There is a programmable interrupt output which can operate in three modes, as a general purpose interrupt to signal when new data is available INT, as an interrupt to indicate when limits are exceeded, or as a pen down interrupt when the screen is touched, PENIRQ. The AD7879 offers temperature and touch-pressure measurement.

It is available in various packages, with either an SPI (AD7879, AD7889) or I2C (AD7879-1, AD7889-1) interface.

See also: tslib - Touchscreen Access Library

See also: AD7877

Driver features and limitations

Software configurable:

  • First Conversion Delay: codes 0-12 are 128 us steps starting at 128 us, codes 13/14/15 are 2.560/3.584/4.096 ms.

  • Acquisition Time (2 us, 4 us, 8 us, 16 us)

  • Average Filter (2, 4, 8, 16)

  • Median Filter (0, 4, 8, 16)

  • Pen Down Acquisition Interval Timer (515 us..9.44 ms in steps of 35 us)

  • Auxiliary GPIO can be exported to GPIOLIB, and therefore used system-wide

Configuration

AD7879-1/AD7889-1 I2C Device Address options:

ADD1

ADD0

I2C Address

0

0

0x2C

0

1

0x2D

1

0

0x2E

1

1

0x2F

Source Code

Status

Source

Mainlined?

ADI tree

Yes

Files

Hardware configuration

https://wiki.analog.com/_media/software/driver/linux/ad7879_example_schematic.png

Adding Linux driver support

Kernel configuration

Configure kernel with make menuconfig (alternatively use make xconfig or make qconfig)

Note

The AD7879 driver depends on CONFIG_SPI or CONFIG_I2C.

Input device support
  -*- Generic input layer (needed for keyboard, mouse, ...)
  < >   Support for memoryless force-feedback devices
  < >   Polled input device skeleton
  < >   Sparse keymap support library
        *** Userland interfaces ***
  < >   Mouse interface
  < >   Joystick interface
  <*>   Event interface
  < >   Event debugging
        *** Input Device Drivers ***
  [ ]   Keyboards  --->
  [ ]   Mice  --->
  [ ]   Joysticks/Gamepads  --->
  [ ]   Tablets  --->
  [*]   Touchscreens  --->

     --- Touchscreens
     < >   ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens (NEW)
     < >   AD7877 based touchscreens
     <*>   Analog Devices AD7879-1/AD7889-1 touchscreen interface (NEW)
        <*>     support I2C bus connection
        < >     support SPI bus connection (NEW)

  [ ]   Miscellaneous devices  --->
      Hardware I/O ports  --->

Driver compiled as a module

root:~> modprobe evdev
root:~> modprobe ad7879-spi   # use ad7879-i2c for the I2C variant
input: AD7879 Touchscreen as /class/input/input0
ad7879 spi0.1: touchscreen, irq 57

Driver compiled into the kernel

Your kernel startup messages should include something like this

input: AD7879 Touchscreen as /class/input/input0
ad7879 spi0.1: touchscreen, irq 57

Devicetree configuration

The driver reads its configuration from devicetree properties. Required properties are compatible (adi,ad7879 for SPI, adi,ad7879-1 for I2C), reg, touchscreen-max-pressure and adi,resistance-plate-x; the last two set the pressure range and X-plate resistance used for the pressure calculation. The conversion settings adi,first-conversion-delay, adi,acquisition-time, adi,median-filter-size, adi,averaging and adi,conversion-interval are u8 properties, written with /bits/ 8. gpio-controller and #gpio-cells = <1> export the auxiliary pin as a one-line GPIO chip. See Documentation/devicetree/bindings/input/touchscreen/adi,ad7879.yaml.

SPI example:

#include <dt-bindings/interrupt-controller/irq.h>

&spi0 {
    #address-cells = <1>;
    #size-cells = <0>;

    touchscreen@1 {
        compatible = "adi,ad7879";
        reg = <1>;
        spi-max-frequency = <5000000>;
        gpio-controller;
        #gpio-cells = <1>;
        interrupt-parent = <&gpio1>;
        interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
        touchscreen-max-pressure = <4096>;
        adi,resistance-plate-x = <120>;
        adi,first-conversion-delay = /bits/ 8 <3>;
        adi,acquisition-time = /bits/ 8 <1>;
        adi,median-filter-size = /bits/ 8 <2>;
        adi,averaging = /bits/ 8 <1>;
        adi,conversion-interval = /bits/ 8 <255>;
    };
};

I2C example:

#include <dt-bindings/interrupt-controller/irq.h>

&i2c0 {
    #address-cells = <1>;
    #size-cells = <0>;

    touchscreen@2c {
        compatible = "adi,ad7879-1";
        reg = <0x2c>;
        interrupt-parent = <&gpio1>;
        interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
        touchscreen-max-pressure = <4096>;
        adi,resistance-plate-x = <120>;
        adi,first-conversion-delay = /bits/ 8 <3>;
        adi,acquisition-time = /bits/ 8 <1>;
        adi,median-filter-size = /bits/ 8 <2>;
        adi,averaging = /bits/ 8 <1>;
        adi,conversion-interval = /bits/ 8 <255>;
    };
};

Driver testing

Identify the device

After boot, identify the touchscreen by reading the input-event device names. Event numbers depend on the other input devices and are not fixed by the AD7879 driver:

for name in /sys/class/input/event*/device/name; do
    [ -f "$name" ] || continue
    printf '%s: ' "${name%/device/name}"
    cat "$name"
done

Use the /dev/input/eventX node corresponding to the AD7879 Touchscreen name for the event tests below. If diagnosing interrupt delivery, inspect /proc/interrupts using the actual board’s registered interrupt; do not assume a fixed IRQ or that the touchscreen is always input0.

Use the event_test utility to test proper function

root:/> event_test /dev/input/event0
Input driver version is 1.0.0
Input device ID: bus 0x0 vendor 0x0 product 0x0 version 0x0
Input device name: "AD7879 Touchscreen"
Supported events:
  Event type 0 (Sync)
  Event type 1 (Key)
    Event code 330 (Touch)
  Event type 3 (Absolute)
    Event code 0 (X)
      Value   1268
      Min        0
      Max     4095
    Event code 1 (Y)
      Value   1250
      Min        0
      Max     4095
    Event code 24 (Pressure)
      Value      0
      Min        0
      Max    10000
Testing ... (interrupt to exit)
Event: time 67435.364000, type 1 (Key), code 330 (Touch), value 1
Event: time 67435.364000, type 3 (Absolute), code 0 (X), value 1624
Event: time 67435.364000, type 3 (Absolute), code 1 (Y), value 1514
Event: time 67435.364000, type 3 (Absolute), code 24 (Pressure), value 349
Event: time 67435.364000, -------------- Report Sync ------------
Event: time 67435.408000, type 3 (Absolute), code 0 (X), value 1626
Event: time 67435.408000, type 3 (Absolute), code 1 (Y), value 1516
Event: time 67435.408000, type 3 (Absolute), code 24 (Pressure), value 342
Event: time 67435.408000, -------------- Report Sync ------------
Event: time 67435.452000, type 3 (Absolute), code 1 (Y), value 1514
Event: time 67435.452000, type 3 (Absolute), code 24 (Pressure), value 339
Event: time 67435.452000, -------------- Report Sync ------------
Event: time 67435.496000, type 3 (Absolute), code 0 (X), value 1625
Event: time 67435.496000, type 3 (Absolute), code 24 (Pressure), value 343
Event: time 67435.496000, -------------- Report Sync ------------
Event: time 67435.596000, type 3 (Absolute), code 24 (Pressure), value 0
Event: time 67435.596000, type 1 (Key), code 330 (Touch), value 0
Event: time 67435.596000, -------------- Report Sync ------------

Tip

In case you touch the surface and don’t receive events, it’s likely that something with your /DAV Interrupt is wrong. Check the IRQ number in the devicetree node.

Tip

In case you get a message like: evtest: No such device, it’s likely that you have not install the necessary modules

root:/> cat /proc/interrupts
  6:       7898   Blackfin Core Timer
 10:          1   rtc-bfin
 18:          0   BFIN_UART_RX
 19:        105   BFIN_UART_TX
 24:         77   EMAC_RX
 42:          0   PPI ERROR
 57:        168   ad7879
Err:          0
root:/>

Device-specific sysfs attributes

The device exports a single sysfs attribute, disable, under its bus device directory (e.g. /sys/bus/spi/devices/spi0.1/disable). Writing 1 disables the touchscreen; writing 0 re-enables it. The auxiliary GPIO, when gpio-controller is set, is registered as a gpiolib GPIO controller.

Touchscreen calibration

See the tslib - Touchscreen Access Library page for more information.

Using the AD7879 in Microwin / Nano-X

User Configuration

  • Enable Microwin during Customize Application/Library Settings

  • Manually edit user/microwin/src/config

Enable: AD7877MOUSE = Y

Disable: NOMOUSE = N

Testing and Calibration

root:/> nano-X &
210
root:/> nanowm &
211
root:/> nxcal <-- TS Calibration Utility
root:/> nxeyes

Nanox with tslib

For kernel after 2.6.22, /dev/input/ts\* interface has been deprecated in linux. Nanox need to use tslib for touchscreen. To enable:

####################################################################
# Mouse drivers
# GPMMOUSE      gpm mouse
# SERMOUSE      serial Microsoft, PC, Logitech, PS/2 mice (/dev/psaux)
# SUNMOUSE      Sun Workstation mouse (/dev/sunmouse)
# NOMOUSE       no mouse driver
#
# Touchscreen drivers
# IPAQMOUSE     Compaq iPAQ, Intel Assabet (/dev/h3600_tsraw)
# ZAURUSMOUSE   Sharp Zaurus (/dev/sharp_ts)
# TUXMOUSE      TuxScreen (/dev/ucb1x00-ts)
# ADSMOUSE      Applied Data Systems GC+ (/dev/ts)
# ADS7846MOUSE          ADS7846 chip, PSI OMAP Innovator (/dev/innnovator_ts)
# EPMOUSE       Embedded Planet (/dev/tpanel)
# VHMOUSE       Vtech Helio (/dev/tpanel)
# MTMOUSE       MicroTouch serial (/dev/ttyS1)
# PSIONMOUSE    Psion 5 (/dev/touch_psion)
# YOPYMOUSE     Yopy (/dev/yopy-ts)
# HARRIERMOUSE  NEC Harrier (/dev/tpanel)
# AD7877MOUSE   Analog Devices AD7877/9 Touch Screen Digitizer (/dev/ts0)
# TSLIBMOUSE    Common touchscreen driver using tslib
####################################################################
GPMMOUSE                 = N
SERMOUSE                 = N
SUNMOUSE                 = N
IPAQMOUSE                = N
ZAURUSMOUSE              = N
TUXMOUSE                 = N
ADSMOUSE                 = N
ADS7846MOUSE             = N
EPMOUSE                  = N
VHMOUSE                  = N
MTMOUSE                  = N
PSIONMOUSE               = N
YOPYMOUSE                = N
HARRIERMOUSE             = N
LIRCMOUSE                = N
AD7879MOUSE              = N
TSLIBMOUSE               = Y
NOMOUSE                  = N

Before start nano-x, need to set up tslib - Touchscreen Access Library first (including running ts_calibrate):

root:/> . /etc/tslib.env
root:/> ts_calibrate
root:/> nano-X &
root:/> nanowm &

Driver Source

Most people should not care about the driver source - it just works as a normal Linux input device. If you are interested, you can look at the driver source:

ad7879_report()

Troubleshooting

Common Problems

In case you see a message like this

spi0.1: Failed to probe AD7879 Touchscreen

This means that the SPI communication and initialization with the AD7879 touchscreen controller/digitizer failed. Check the SPI chip select and bus number in the devicetree node.