Examples

Relative Mode example

A simple example of using the Pinnacle ASIC in relative mode.

examples/cirque_pinnacle_relative_mode.py
 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
import time
import board
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    RelativeReport,
    PINNACLE_RELATIVE,
)

IS_ON_LINUX = sys.platform.lower() == "linux"

print("Cirque Pinnacle relative mode\n")

# a HW ``dr_pin`` is more efficient, but not required for Absolute or Relative modes
dr_pin = None
if not input("Use SW Data Ready? [y/N] ").lower().startswith("y"):
    print("-- Using HW Data Ready pin.")
    dr_pin = DigitalInOut(board.D7 if not IS_ON_LINUX else board.D25)

if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"):
    print("-- Using SPI interface.")
    spi = board.SPI()
    ss_pin = DigitalInOut(board.D2 if not IS_ON_LINUX else board.CE0)
    trackpad = PinnacleTouchSPI(spi, ss_pin, dr_pin=dr_pin)
else:
    print("-- Using I2C interface.")
    i2c = board.I2C()
    trackpad = PinnacleTouchI2C(i2c, dr_pin=dr_pin)

trackpad.data_mode = PINNACLE_RELATIVE  # ensure mouse mode is enabled
trackpad.relative_mode_config(True)  # enable tap detection

# an object to hold the data reported by the Pinnacle
data = RelativeReport()


def print_data(timeout=6):
    """Print available data reports from the Pinnacle touch controller
    until there's no input for a period of ``timeout`` seconds."""
    print(
        "Touch the trackpad to see the data. Exits after",
        timeout,
        "seconds of inactivity.",
    )
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        while trackpad.available():  # is there new data?
            trackpad.read(data)
            print(data)
            start = time.monotonic()


Absolute Mode example

A simple example of using the Pinnacle ASIC in absolute mode.

examples/cirque_pinnacle_absolute_mode.py
 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
import time
import board
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,  # noqa: imported-but-unused
    PINNACLE_ABSOLUTE,
    AbsoluteReport,
)

IS_ON_LINUX = sys.platform.lower() == "linux"

print("Cirque Pinnacle absolute mode\n")

# a HW ``dr_pin`` is more efficient, but not required for Absolute or Relative modes
dr_pin = None
if not input("Use SW Data Ready? [y/N] ").lower().startswith("y"):
    print("-- Using HW Data Ready pin.")
    dr_pin = DigitalInOut(board.D7 if not IS_ON_LINUX else board.D25)

if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"):
    print("-- Using SPI interface.")
    spi = board.SPI()
    ss_pin = DigitalInOut(board.D2 if not IS_ON_LINUX else board.CE0)
    trackpad = PinnacleTouchSPI(spi, ss_pin, dr_pin=dr_pin)
else:
    print("-- Using I2C interface.")
    i2c = board.I2C()
    trackpad = PinnacleTouchI2C(i2c, dr_pin=dr_pin)

trackpad.data_mode = PINNACLE_ABSOLUTE  # ensure Absolute mode is enabled
trackpad.absolute_mode_config(z_idle_count=1)  # limit idle packet count to 1

# an object to hold the data reported by the Pinnacle
data = AbsoluteReport()


def print_data(timeout=6):
    """Print available data reports from the Pinnacle touch controller
    until there's no input for a period of ``timeout`` seconds."""
    print(
        "Touch the trackpad to see the data. Exits after",
        timeout,
        "seconds of inactivity.",
    )
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        while trackpad.available():  # is there new data?
            trackpad.read(data)
            # specification sheet recommends clamping absolute position data of
            # X & Y axis for reliability
            if data.z:  # only clamp values if Z axis is not idle.
                data.x = max(128, min(1920, data.x))  # X-axis
                data.y = max(64, min(1472, data.y))  # Y-axis
            print(data)
            start = time.monotonic()


def print_trig(timeout=6):
    """Print available data reports from the Pinnacle touch controller as trigonometric
    calculations until there's no input for a period of ``timeout`` seconds."""
    print(
        "Touch the trackpad to see the data. Exits after",
        timeout,
        "seconds of inactivity.",
    )
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        while trackpad.available():  # is there new data?
            trackpad.read(data)

            if not data.z:  # if not touching (or near) the sensor
                print("Idling")  # don't do calc when both axes are 0
            else:  # if touching (or near) the sensor
                # datasheet recommends clamping X & Y axis for reliability
                data.x = max(128, min(1920, data.x))  # 128 <= x <= 1920
                data.y = max(64, min(1472, data.y))  # 64 <= y <= 1472

                # coordinates assume axes have been clamped to recommended ranges
                coord_x = data.x - 960
                coord_y = data.y - 736  # NOTE: y-axis is inverted by default
                radius = math.sqrt(math.pow(coord_x, 2) + math.pow(coord_y, 2))
                # angle (in degrees) ranges [-180, 180];
                angle = math.atan2(coord_y, coord_x) * 180 / math.pi
                print("angle: %.02f\tradius: %.02f" % (angle, radius))
            start = time.monotonic()


Anymeas mode example

This example uses the Pinnacle touch controller’s anymeas mode to fetch raw ADC values.

examples/cirque_pinnacle_anymeas_mode.py
 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
import time
import board
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    PINNACLE_ANYMEAS,
)

IS_ON_LINUX = sys.platform.lower() == "linux"

print("Cirque Pinnacle anymeas mode\n")

# Using HW Data Ready pin as required for Anymeas mode
dr_pin = DigitalInOut(board.D7 if not IS_ON_LINUX else board.D25)

if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"):
    print("-- Using SPI interface.")
    spi = board.SPI()
    ss_pin = DigitalInOut(board.D2 if not IS_ON_LINUX else board.CE0)
    trackpad = PinnacleTouchSPI(spi, ss_pin, dr_pin=dr_pin)
else:
    print("-- Using I2C interface.")
    i2c = board.I2C()
    trackpad = PinnacleTouchI2C(i2c, dr_pin=dr_pin)

trackpad.data_mode = PINNACLE_ANYMEAS

vectors = [
    #  toggle  ,   polarity
    (0x00010000, 0x00010000),  # This toggles Y0 only and toggles it positively
    (0x00010000, 0x00000000),  # This toggles Y0 only and toggles it negatively
    (0x00000001, 0x00000000),  # This toggles X0 only and toggles it positively
    (0x00008000, 0x00000000),  # This toggles X16 only and toggles it positively
    (0x00FF00FF, 0x000000FF),  # This toggles Y0-Y7 negative and X0-X7 positive
]

# a list of compensations to use with measured `vectors`
compensation = [0] * len(vectors)


def compensate(count=5):
    """Take ``count`` measurements, then average them together (for each vector)"""
    for i, (toggle, polarity) in enumerate(vectors):
        compensation[i] = 0
        for _ in range(count):
            result = trackpad.measure_adc(toggle, polarity)
            compensation[i] += result
        compensation[i] = int(compensation[i] / count)
        print("compensation {}: {}".format(i, compensation[i]))


def take_measurements(timeout=6):
    """Read ``len(vectors)`` number of measurements and print results for
    ``timeout`` number of seconds."""
    print("Taking measurements for", timeout, "seconds.")
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        for i, (toggle, polarity) in enumerate(vectors):
            result = trackpad.measure_adc(toggle, polarity)
            print("meas{}: {}".format(i, result - compensation[i]), end="\t")
        print()


USB Mouse example

This example uses CircuitPython’s built-in usb_hid API to emulate a mouse with the Cirque circle trackpad.

examples/cirque_pinnacle_usb_mouse.py
 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
import time
import board
from digitalio import DigitalInOut
import usb_hid
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    PINNACLE_RELATIVE,
    RelativeReport,
)

IS_ON_LINUX = sys.platform.lower() == "linux"

print("Cirque Pinnacle as a USB mouse\n")

# a HW ``dr_pin`` is more efficient, but not required for Absolute or Relative modes
dr_pin = None
if not input("Use SW Data Ready? [y/N] ").lower().startswith("y"):
    print("-- Using HW Data Ready pin.")
    dr_pin = DigitalInOut(board.D7 if not IS_ON_LINUX else board.D25)

if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"):
    print("-- Using SPI interface.")
    spi = board.SPI()
    ss_pin = DigitalInOut(board.D2 if not IS_ON_LINUX else board.CE0)
    trackpad = PinnacleTouchSPI(spi, ss_pin, dr_pin=dr_pin)
else:
    print("-- Using I2C interface.")
    i2c = board.I2C()
    trackpad = PinnacleTouchI2C(i2c, dr_pin=dr_pin)

trackpad.data_mode = PINNACLE_RELATIVE  # ensure mouse mode is enabled
# tell the Pinnacle ASIC to rotate the orientation of the axis data by +90 degrees
trackpad.relative_mode_config(rotate90=True)

# an object to hold the data reported by the Pinnacle
data = RelativeReport()

mouse = None
for dev in usb_hid.devices:
    # be sure we're grabbing the mouse singleton
    if dev.usage == 2 and dev.usage_page == 1:
        mouse = dev
        break
else:
    raise OSError("mouse HID device not available.")
# mouse.send_report() takes a 4 byte buffer in which
#   byte0 = buttons in which
#       bit5 = back, bit4 = forward, bit2 = middle, bit1 = right, bit0 = left
#   byte1 = delta x-axis
#   byte2 = delta y-axis
#   byte3 = delta scroll wheel


def move(timeout=10):
    """Send mouse X & Y reported data from the Pinnacle touch controller
    until there's no input for a period of ``timeout`` seconds."""
    print(
        "Trackpad acting as a USB mouse device until", timeout, "seconds of inactivity."
    )
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        while trackpad.available():
            trackpad.read(data)
            data.x *= -1  # invert x-axis
            mouse.send_report(data.buffer)
            start = time.monotonic()  # reset timeout

    mouse.send_report(b"\x00" * 4)  # release buttons (just in case)