Skip to content

Instantly share code, notes, and snippets.

@PaulskPt
Created February 25, 2024 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaulskPt/74a0743edc7fb7cf522de2e621b7ce7e to your computer and use it in GitHub Desktop.
Save PaulskPt/74a0743edc7fb7cf522de2e621b7ce7e to your computer and use it in GitHub Desktop.
Adafruit GamepadQT with Raspberry Pi 5B-8GB
# _*_ coding: utf-8 _*_
# SPDX-FileCopyrightText: 2024 Paulus Schulinck
#
# SPDX-License-Identifier: MIT
##############################
# NOTE: Blinka and other prerequisites have to be installed on the Raspberry Pi
# See: https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi
# Also: before running this script, activate the venv environment as explained in the Adafruit article.
# This script is tested on a Raspberry Pi 5B-8GB and an Adafruit Gamepad QT (product ID 5743),
# connected through a Sparkfun Qwiic PiHat (https://www.sparkfun.com/products/14459)
import sys, os
import time
import board
import busio
from micropython import const
from adafruit_seesaw.seesaw import Seesaw
from adafruit_platformdetect import Detector
detector = Detector()
print("Board id: ", detector.board.id)
print("Board serial: ", detector.get_cpuinfo_field('Serial'))
print("Board rev: ", detector.get_cpuinfo_field('Revision'))
i2c = busio.I2C(board.SCL, board.SDA)
selected_group = 0
nr_groups = 2
BUTTON_SELECT = const(0)
BUTTON_B = const(1)
BUTTON_Y = const(2)
BUTTON_A = const(5)
BUTTON_X = const(6)
BUTTON_START = const(16)
button_mask = const(
( 1 << BUTTON_X) # = 1 << 6 = 64 = 0x00040
| (1 << BUTTON_Y) # = 1 << 2 = 4 = 0x00004
| (1 << BUTTON_A) # = 1 << 5 = 32 = 0x00020
| (1 << BUTTON_B) # = 1 << 1 = 2 = 0x00002
| (1 << BUTTON_SELECT) # = 1 << 0 = 1 = 0x00001
| (1 << BUTTON_START) # = 1 << 16 = 65536 = 0x10000
) # = 65639 dec or 0x10067
# Raspberry Pi 5B-8GB i2c devices found:
# /dev/i2c-1
# /dev/i2c-11
# /dev/i2c-12
try:
seesaw = Seesaw(i2c, addr=0x50)
seesaw.pin_mode_bulk(button_mask, seesaw.INPUT_PULLUP)
qt_btns_present = True
except Exception as e:
print(f"global(): Error while creating an instance of seesaw class: {e}")
qt_btns_present = False
raise
def ck_usr_answr():
ret = False
while True:
answer = input("Are you sure? (Y/n)+<Enter>: ")
print(f"You answered: \'{answer}\'")
if answer == "Y" or answer == "y":
ret = True
break
elif answer == "N" or answer == "n":
break
return ret
def reboot():
print("\nRebooting...")
time.sleep(3)
os.system('sudo shutdown -r now')
def pr_btn_name(res):
btns = ["X", "Y", "A", "B", "Select", "Start"]
if res >= 0 and res < len(btns):
print("Button "+btns[res]+" pressed")
def gamepad_test():
TAG= "gamepad_test(): "
id = seesaw.chip_id
version = seesaw.get_version() # None
s_id = "seesaw.chip_id"
s = "{:s}= 0x{:x}".format(s_id, id)
v = "seesaw._version()= 0x{:x}".format(version)
print(TAG+s)
print(TAG+v)
seesaw.pin_mode_bulk(button_mask, seesaw.INPUT_PULLUP)
last_x = 0
last_y = 0
elapsed_t = None
interval_t = 36
interval_cnt = 0
msg1_shown = False
nr_btns = 6
res_x = res_y = res_a = res_b = res_sel = res_sta = -1
start_t = time.monotonic()
while True:
if not msg1_shown:
msg1_shown = True
print(TAG+"We\'re going to test the gamepad.\n\t\t"+ \
"Press a button on the gamepad...\n\t\t"+ \
"To reboot the Raspberry Pi press gamepad button Start\n")
try:
x = 1023 - seesaw.analog_read(14)
y = 1023 - seesaw.analog_read(15)
except Exception as e:
if e.errno == 121: # Remote I/O Error
print(f"Error: {e}")
pass
if (abs(x - last_x) > 3) or (abs(y - last_y) > 3):
print(f"joystick: (x, y)= ({x}, {y})")
last_x = x
last_y = y
buttons = seesaw.digital_read_bulk(button_mask)
if buttons:
res = -1
for _ in range(nr_btns):
if _ == 0:
bz = 1 << BUTTON_X
if not buttons & (bz):
res = _
if res_x != res:
pr_btn_name(res)
res_x = res
break
if _ == 1:
bz = 1 << BUTTON_Y
if not buttons & (bz):
res = _
if res_y != res:
pr_btn_name(res)
res_y = res
break
if _ == 2:
bz = 1 << BUTTON_A
if not buttons & (bz):
res = _
if res_a != res:
pr_btn_name(res)
res_a = res
break
if _ == 3:
bz = 1 << BUTTON_B
if not buttons & (bz):
res = _
if res_b != res:
pr_btn_name(res)
res_b = res
break
if _ == 4:
bz = 1 << BUTTON_SELECT
if not buttons & (bz):
res = _
if res_sel != res:
pr_btn_name(res)
res_sel = res
break
if _ == 5:
bz = 1 << BUTTON_START
if not buttons & (bz):
res = _
if res_sta != res:
pr_btn_name(res)
res_sta = res
print("About to reboot the Raspberry Pi")
if ck_usr_answr():
reboot() # Reboot the RPi5
else:
msg1_shown = False
res_sta = -2
break
curr_t = time.monotonic()
elapsed_t = (curr_t - start_t) * 1000
if elapsed_t >= interval_t:
interval_cnt += 1
if interval_cnt >= 100:
interval_cnt = 0
res_x = res_y = res_a = res_b = res_sel = res_sta = -2
start_t = curr_t
time.sleep(0.01)
def main():
TAG= "main(): "
loopnr = 0
while True:
try:
loopnr += 1
# print(TAG+f"\nLoopnr: {loopnr}")
if loopnr >= 100:
loopnr = 0
gamepad_test()
except KeyboardInterrupt:
print(TAG+"KeyboardInterrrupt. Exiting...")
break
if loopnr >= 1000:
break
sys.exit()
if __name__ == '__main__':
main()
Thursday 2024-02-22 12h49 utc
Board: Raspberry Pi 5B-8GB
Python script: gamepadqt.py
Python print output:
(env) paulsk@raspi5B-8GB:~/Adafruit_GamepadQT $ python3 gamepadqt.py
Board id: RASPBERRY_PI_5
Board serial: 1169efc3bd80e900
Board rev: d04170
gamepad_test(): seesaw.chip_id= 0x87
gamepad_test(): seesaw._version()= 0x166f7a97
gamepad_test(): We're going to test the gamepad.
Press a button on the gamepad...
To reboot the Raspberry Pi press gamepad button Start
joystick: (x, y)= (504, 511)
Button B pressed
Button A pressed
Button Y pressed
Button X pressed
Button Select pressed
Button Start pressed
About to reboot the Raspberry Pi
Are you sure? (Y/n)+<Enter>: n
You answered: 'n'
gamepad_test(): We're going to test the gamepad.
Press a button on the gamepad...
To reboot the Raspberry Pi press gamepad button Start
^Cmain(): KeyboardInterrrupt. Exiting...
(env) paulsk@raspi5B-8GB:~/Adafruit_GamepadQT $
@PaulskPt
Copy link
Author

Today I connected the Sparkfun Qwiic PiHat and the Adafruit GamepadQT to a Raspberry CM4. It worked, however there were spurious keypress events. I was able to solve these unwanted spurious keypress events by inserting the line: dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,bus=1 to file: /boot/firmware/config.txt under [cm4].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment