adafruit / Adafruit_seesawPeripheral

Arduino library for making seesaw peripherals using Arduino core!
Other
21 stars 12 forks source link

OPTIONS function register not implemented #24

Open PaulskPt opened 4 months ago

PaulskPt commented 4 months ago

I wrote a python script to use an Adafruit Gamepad QT (Prod ID 5743) to a Raspberry Pi 5B-8GB. Installed Blinka and all other requirements. Everything is running fine except that a call to function seesaw.get_options causes a Remote I/O Error (Errno 121). To see what is happening I added a print statement inside the function seesaw.read().

Print output of my Python script:


(env) paulsk@raspi5B-8GB:~/Adafruit_GamepadQT $ python3 gamepadqt.py
Board id:      RASPBERRY_PI_5
Board serial:  1169efc3bd80e900
Board rev:     d04170
env/lib/python3.11/site-packages/adafruit_seesaw/seesaw.py/seesaw.read()
        params reg_base: 0x0, reg: 0x1, buf: bytearray(b'\x00')                           <<<=== _STATUS_HW_ID
env/lib/python3.11/site-packages/adafruit_seesaw/seesaw.py/seesaw.read()
        params reg_base: 0x0, reg: 0x2, buf: bytearray(b'\x00\x00\x00\x00')               <<<=== _STATUS_VERSION 
env/lib/python3.11/site-packages/adafruit_seesaw/seesaw.py/seesaw.read()
        params reg_base: 0x0, reg: 0x2, buf: bytearray(b'\x00\x00\x00\x00')               <<<=== _STATUS_VERSION 
env/lib/python3.11/site-packages/adafruit_seesaw/seesaw.py/seesaw.read()
        params reg_base: 0x0, reg: 0x3, buf: bytearray(b'\x00\x00\x00\x00')               <<<=== _STATUS_OPTIONS
seesaw.read(): Error: [Errno 121] Remote I/O error                                        <<<=== The error
gamepad_test(): seesaw.chip_id= 0x87
gamepad_test(): seesaw._version()= 0x166f7a97 hex
gamepad_test(): seesaw.get_options()= 0x0 hex
gamepad_test(): We're going to test the gamepad.
                Press a button on the gamepad...
                To reboot the Raspberry Pi press gamepad button Start

To prevent the script crashes because of the error I added a try...except block inside the function seesaw.options(), as follows:

def get_options(self):
        """Retrieve the 'options' word from the SeeSaw board"""
        buf = bytearray(4)
        try:
            self.read(_STATUS_BASE, _STATUS_OPTIONS, buf)
        except OSError as e:
            if e.errno == 121:  # remote I/O Error
                print(f"seesaw.get_options(): Error: {e}")
                pass
        ret = struct.unpack(">I", buf)[0]
        return ret

QUESTION: I would like to know what is causing this error.

caternuson commented 4 months ago

I've repeated this with a test setup using a Pi4.

Tried hardware I2C speeds of 10kHz and 400kHz and it did not help.

Also tried a software I2C setup:

dtoverlay=i2c-gpio,i2c_gpio_sda=16,i2c_gpio_scl=20,bus=8

and it also has issues, but different:

>>> seesaw.get_options()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/blinka/lib/python3.11/site-packages/adafruit_seesaw/seesaw.py", line 205, in get_options
    self.read(_STATUS_BASE, _STATUS_OPTIONS, buf)
  File "/home/pi/blinka/lib/python3.11/site-packages/adafruit_seesaw/seesaw.py", line 508, in read
    i2c.readinto(buf)
  File "/home/pi/blinka/lib/python3.11/site-packages/adafruit_bus_device/i2c_device.py", line 81, in readinto
    self.i2c.readfrom_into(self.device_address, buf, start=start, end=end)
  File "/home/pi/blinka/lib/python3.11/site-packages/busio.py", line 197, in readfrom_into
    return self._i2c.readfrom_into(address, buffer, stop=True)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pi/blinka/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py", line 67, in readfrom_into
    readin = self._i2c_bus.read_bytes(address, end - start)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pi/blinka/lib/python3.11/site-packages/Adafruit_PureIO/smbus.py", line 170, in read_bytes
    return self._device.read(number)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 6] No such device or address
caternuson commented 4 months ago

Native CP also has issues:

Adafruit CircuitPython 8.2.10 on 2024-02-14; Adafruit QT2040 Trinkey with rp2040
>>> import board
>>> from adafruit_seesaw.seesaw import Seesaw
>>> i2c = board.STEMMA_I2C()
>>> seesaw = Seesaw(i2c, addr=0x50)
>>> seesaw.get_version()
376404631
>>> seesaw.analog_read(14)
506
>>> seesaw.get_options()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "adafruit_seesaw/seesaw.py", line 205, in get_options
  File "adafruit_seesaw/seesaw.py", line 508, in read
OSError: [Errno 19] No such device
>>> 
caternuson commented 4 months ago

Nothing weird in I2C traffic (using same QT2040 Trinkey from above).

Here's the call to seesaw.get_options(): image That's the initial write request, a ~8ms sleep which is coming from the library, and then the attempt to read the 4 bytes.

The write is what is should be: image but the read attempt is NAK'd right away: image

That would seem to indicate something more with the firmware itself.

caternuson commented 4 months ago

This is a limitation of the current version of the seesaw firmware being used on the Adafruit Gamepad QT (Prod ID 5743).

The OPTIONS function of the STATUS base register has not been implemented yet: https://github.com/adafruit/Adafruit_seesawPeripheral/blob/313090f3a3839e1e5f8f0d7a81c6a6262f89f571/Adafruit_seesawPeripheral_request.h#L25-L31 Only HW_ID and VERSION have been implemented.

Note that an attempt to read the TEMP register also fails in a similar way:

>>> seesaw.get_temp()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "adafruit_seesaw/seesaw.py", line 386, in get_temp
  File "adafruit_seesaw/seesaw.py", line 508, in read
OSError: [Errno 19] No such device
>>> 

@PaulskPt What is your use case for needing to query the OPTIONS register?

PaulskPt commented 4 months ago

@caternuson Thank you for your four reactions. I used the adafruit_seesaw module for CircuitPython also. I also got the OSError "No such device" various times. I have no special use case to query the OPTIONS register. However, since the function is present in the Seesaw class, It did an attempt to call it. More in a sense or understanding the device better.

caternuson commented 4 months ago

OK. That particular register isn't super useful for normal usage. Which is why it probably hasn't be implemented yet.

I'm going to move this issue to the firmware repo since it's a firmware issue, not a library issue.

PaulskPt commented 4 months ago

@caternuson . I see that you transferred my issue from adafruit/Adafruit_CircuitPython_seesaw to this repo: adafruit/AdafruitseesawPeripheral, however this repo I don't use. I guess it does the same. In the discussion of my initial issue I read in one of your comments that you had been experiencing spurious keypress events (my words because I don't remember the wording exactly). Today I used my gamepadqt.py script on a Raspberry CM4. While I had no spurious keypress events on the Raspberry Pi 5B-8GB, I had them on the CM4. I applied a modified version of your mod to /boot/firmware/config.txt. I inserted the line under [cm4]. The added line is:

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,bus=1  

because the Adafruit GamepadQT is at /dev/i2c-1. After this addition the spurious keypress events disappeared on the CM4.

caternuson commented 4 months ago

The Adafruit_CircuitPython_seesaw repo is just a library for using seesaw based boards. This repo is the actual firmware running on the seesaw board itself (for ATtiny based seesaw boards) - which is where the actual issue resides.

PaulskPt commented 4 months ago

Thank you for this explanation.