2bndy5 / CircuitPython_Cirque_Pinnacle

A CircuitPython driver library for interfacing with the Cirque Pinnacle (1CA027) touch controller ASIC used in Cirque Circle Trackpads.
http://circuitpython-cirque-pinnacle.rtfd.io/
MIT License
16 stars 0 forks source link

I2C on RP2040 has problems #4

Open ilukinov opened 1 year ago

ilukinov commented 1 year ago

Hi, thanks for the working on this) Please provide examples for microcontrollers if possible. Thanks

EDIT: see below https://github.com/2bndy5/CircuitPython_Cirque_Pinnacle/issues/4#issuecomment-1576160780 for actual issue/problem.

2bndy5 commented 1 year ago

In Python?

ilukinov commented 1 year ago

yes

2bndy5 commented 1 year ago

Sorry, I thought this was my Arduino-based lib for the same sensor.

The examples provided work with RP2040-based boards, but you just have to change the pin numbers.

2bndy5 commented 1 year ago

I know because I tested it. Last time I tested it, the I2C interface on the itsybitsy RP2040 is buggy (not a lib issue - it was a circuitpython issue). SPI works fine on the itsbitsy RP2040.

2bndy5 commented 1 year ago

Just in case you didn't find them, the examples are hosted with the lib here on github. You can also browse the docs and copy the examples' code from the docs' examples page.

ilukinov commented 1 year ago

Thanks, I found examples right away. Maybe I'm doing something wrong here. When I use example below it will say that device is not found (I'm using rp2040 Zero board, it doesn't have board.I2C() so I have to do it manually):

import time
import board
import busio
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    RelativeReport,
    PINNACLE_RELATIVE,
)

print("-- Using I2C interface.")
dr_pin = DigitalInOut(board.GP1)
i2c = busio.I2C(board.GP27, board.GP26)
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()

output: Using I2C interface. Traceback (most recent call last): File "code.py", line 16, in <module> File "/lib/circuitpython_cirque_pinnacle.py", line 905, in __init__ ValueError: No I2C device at address: 0x2a Which is odd, because if I try code below it works just fine and outputs 42(0x2a)

import busio
import board

i2c = busio.I2C(board.GP27, board.GP26)
i2c.try_lock()
print('\n i2c scan: ' + str(i2c.scan()))
i2c.unlock()

output: i2c scan: [42]

Now if I change your example code to:

import time
import board
import busio
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    RelativeReport,
    PINNACLE_RELATIVE,
)

print("-- Using I2C interface.")
dr_pin = DigitalInOut(board.GP1)
i2c = busio.I2C(board.GP27, board.GP26)
i2c.try_lock()
print('\n i2c scan: ' + str(i2c.scan()))
i2c.unlock()
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()

print_data()

output: i2c scan: [42] 7 58 Touch the trackpad to see the data. Exits after 6 seconds of inactivity. it will find trackpad now, but trackpad.available() will always be False (I tried with and without dr_pin) I know that it can find touchpad because I added line to output firmware version to your code

print(firmware_id, firmware_ver)

it outputs:
7 58(0x3A)

Any advice on how to figure out what is happening?

p.s. R1 is removed on the touchpad.

2bndy5 commented 1 year ago

Yeah, that's the bug I hit in CircuitPython. You already found the workaround. You have to manually check the device exists before init-ing the PinnacleTouch object. After that, everything worked fine.

To be clear, this is a bug in CircuitPython on the RP2040 boards. The same lib code works fine on the ATSAMD51 chip.

2bndy5 commented 1 year ago

I also asked about this problem at the Adafruit Forums but got no response. So maybe its time to elevate this as a new issue over at adafruit/circuitpython repo.

FYI, this problem seems similar to adafruit/circuitpython#5871, but that was for espressif chips. Also this issue adafruit/circuitpython#4621 for the RP2040 boards seems related.

ilukinov commented 1 year ago

Well that's a bummer :( But as I mention even after workaround it still doesn't work for me

2bndy5 commented 1 year ago

trackpad.available() will always be False (I tried with and without dr_pin)

I didn't catch that. Does track.pad.feed_enable == True?

2bndy5 commented 1 year ago

IDK if you're proficient in C/C++, but I have a CirquePinnacle lib that explicitly supports the PicoSDK (includes specific examples). That lib tested much better on the same RP2040 board that hit that CircuitPython bug. In my experience, C/C++ is significantly faster on microcontrollers. But if you're tied to other dependencies/libs in CircuitPython, then that solution won't be entirely feasible.

ilukinov commented 1 year ago

trackpad.feed_enable is True. I am not that proficient in C/C++ :( I planned to use your lib with kmk firmware to have wireless keyboard with touchpad as a mouse (after making it work on rp2040 plan was to move to nrf52840).

2bndy5 commented 1 year ago

Sorry I haven't hit any problems like "available() always False". I suppose you could also directly check the DR pin without using available(), but that seems redundant given how basic this lib's src code is around the dr_pin. I think this might be another RP2040-specific problem, and will try to investigate/reproduce soon...

2bndy5 commented 1 year ago

I don't recall testing this on my various nRF52 boards (which were purchased to develop for nRF24 org). Please raise a new issue if you find other problems.