Merge branch 'main' of https://github.com/adafruit/Raspberry-Pi-Installer-Scripts into i2smic-nonint-patch-2

This commit is contained in:
Melissa LeBlanc-Williams 2022-11-09 09:54:37 -08:00
commit 45dc7155b2
18 changed files with 1315 additions and 220 deletions

545
adafruit-pitft-mipi.py Executable file
View file

@ -0,0 +1,545 @@
"""
Adafruit PiTFT Installer Script
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
"""
import time
import os
try:
import click
except ImportError:
raise RuntimeError("The library 'Click' was not found. To install, try typing: sudo pip3 install Click")
try:
from adafruit_shell import Shell
except ImportError:
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
shell = Shell()
shell.group = 'PITFT-MIPI'
__version__ = "1.0.0"
"""
This is the main configuration. Displays should be placed in the order
they are to appear in the menu.
"""
config = [
{
"type": "28r",
"menulabel": "PiTFT 2.4\", 2.8\" or 3.2\" resistive (240x320)",
"product": "2.8\" resistive, PID 1601",
"touchscreen": {
"identifier": "STMPE Touchscreen Calibration",
"product": "stmpe",
"transforms": {
"0": "0.988809 -0.023645 0.060523 -0.028817 1.003935 0.034176 0 0 1",
"90": "0.014773 -1.132874 1.033662 1.118701 0.009656 -0.065273 0 0 1",
"180": "-1.115235 -0.010589 1.057967 -0.005964 -1.107968 1.025780 0 0 1",
"270": "-0.033192 1.126869 -0.014114 -1.115846 0.006580 1.050030 0 0 1",
},
"calibrations": {
"0": "4232 11 -879396 1 5786 -752768 65536",
"90": "33 -5782 21364572 4221 35 -1006432 65536",
"180": "-4273 61 16441290 4 -5772 21627524 65536",
"270": "-9 5786 -784608 -4302 19 16620508 65536",
},
"overlay": "touch-stmpe",
},
"mipi_data": {
"command_bin": "adafruit_ili9341_drm",
"gpio": "dc-gpio=25",
"viewport": {
"90": "width=320,height=240",
"180": "width=240,height=320",
"270": "width=320,height=240",
"0": "width=240,height=320",
},
},
"width": 320,
"height": 240,
},
{
"type": "22",
"menulabel": "PiTFT 2.2\" no touch",
"product": "2.2\" no touch",
"mipi_data": {
"command_bin": "adafruit_ili9341_drm",
"gpio": "dc-gpio=25",
"viewport": {
"90": "width=320,height=240",
"180": "width=240,height=320",
"270": "width=320,height=240",
"0": "width=240,height=320",
},
},
"width": 320,
"height": 240,
},
{
"type": "28c",
"menulabel": "PiTFT 2.8\" capacitive touch",
"product": "2.8\" capacitive, PID 1983",
"touchscreen": {
"identifier": "FocalTech Touchscreen Calibration",
"product": "EP0110M09",
"transforms": {
"0": "-1 0 1 0 -1 1 0 0 1",
"90": "0 1 0 -1 0 1 0 0 1",
"180": "1 0 0 0 1 0 0 0 1",
"270": "0 -1 1 1 0 0 0 0 1",
},
"calibrations": "320 65536 0 -65536 0 15728640 65536",
"overlay": "touch-ft6236",
},
"mipi_data": {
"command_bin": "adafruit_ili9341_drm",
"gpio": "dc-gpio=25",
"viewport": {
"90": "width=320,height=240",
"180": "width=240,height=320",
"270": "width=320,height=240",
"0": "width=240,height=320",
},
},
"width": 320,
"height": 240,
},
{
"type": "35r",
"menulabel": "PiTFT 3.5\" resistive touch",
"product": "3.5\" Resistive",
"touchscreen": {
"identifier": "STMPE Touchscreen Calibration",
"product": "stmpe",
"transforms": {
"0": "-1.098388 0.003455 1.052099 0.005512 -1.093095 1.026309 0 0 1",
"90": "-0.000087 1.094214 -0.028826 -1.091711 -0.004364 1.057821 0 0 1",
"180": "1.102807 0.000030 -0.066352 0.001374 1.085417 -0.027208 0 0 1",
"270": "0.003893 -1.087542 1.025913 1.084281 0.008762 -0.060700 0 0 1",
},
"calibrations": {
"0": "5724 -6 -1330074 26 8427 -1034528 65536",
"90": "5 8425 -978304 -5747 61 22119468 65536",
"180": "-5682 -1 22069150 13 -8452 32437698 65536",
"270": "3 -8466 32440206 5703 -1 -1308696 65536",
},
"overlay": "touch-stmpe",
},
"mipi_data": {
"command_bin": "adafruit_hx8357_drm",
"gpio": "dc-gpio=25",
"viewport": {
"90": "width=480,height=320",
"180": "width=320,height=480",
"270": "width=480,height=320",
"0": "width=320,height=480",
},
},
"width": 480,
"height": 320,
"x11_scale": 1.5,
},
{
"type": "st7789_240x240",
"menulabel": "PiTFT Mini 1.3\" or 1.54\" display",
"product": "1.54\" or 1.3\" no touch",
"mipi_data": {
"command_bin": "adafruit_st7789_drm",
"gpio": "dc-gpio=25,backlight-gpio=22",
"viewport": {
"0": "width=240,height=240",
"90": "width=240,height=240,x-offset=80",
"180": "width=240,height=240,y-offset=80",
"270": "width=240,height=240",
},
},
"width": 240,
"height": 240,
},
{
"type": "st7789_240x320",
"menulabel": "ST7789V 2.0\" no touch",
"product": "2.0\" no touch",
"mipi_data": {
"command_bin": "adafruit_st7789_drm",
"gpio": "dc-gpio=25,backlight-gpio=22",
"viewport": {
"0": "width=320,height=240",
"90": "width=240,height=320",
"180": "width=320,height=240",
"270": "width=240,height=320",
},
},
"width": 320,
"height": 240,
},
{
"type": "st7789_240x135",
"menulabel": "MiniPiTFT 1.14\" display",
"product": "1.14\" no touch",
"mipi_data": {
"command_bin": "adafruit_st7789_drm",
"gpio": "dc-gpio=25,backlight-gpio=22",
"viewport": {
"0": "width=136,height=240,x-offset=52,y-offset=40",
"90": "width=240,height=136,y-offset=52,x-offset=40",
"180": "width=136,height=240,x-offset=52,y-offset=40",
"270": "width=240,height=136,y-offset=52,x-offset=40",
},
},
"width": 240,
"height": 135,
},
{
"type": "st7789v_bonnet_240x240",
"menulabel": "TFT 1.3\" Bonnet + Joystick",
"product": "1.3\" Joystick",
"mipi_data": {
"command_bin": "adafruit_st7789_drm",
"gpio": "dc-gpio=25,backlight-gpio=22",
"viewport": {
"0": "width=240,height=240",
"90": "width=240,height=240,x-offset=80",
"180": "width=240,height=240,y-offset=80",
"270": "width=240,height=240",
},
},
"width": 240,
"height": 240,
},
]
# default mipi data
mipi_data = {
"speed": 40000000,
"spi": "spi0-0",
}
PITFT_ROTATIONS = ("90", "180", "270", "0")
UPDATE_DB = False
SYSTEMD = None
MIPI_MINIMUM_KERNEL = 5.15
pitft_config = None
pitftrot = None
auto_reboot = None
def warn_exit(message):
shell.warn(message)
shell.exit(1)
def print_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
print("Adafruit PiTFT Helper v{}".format(__version__))
shell.exit(1)
def progress(ellipsis_count):
for i in range(ellipsis_count):
print("...", end='')
time.sleep(1)
print("")
def sysupdate():
global UPDATE_DB
if not UPDATE_DB:
print("Updating apt indexes...", end='')
progress(3)
if not shell.run_command('sudo apt update', True):
warn_exit("Apt failed to update indexes!")
if not shell.run_command('sudo apt-get update', True):
warn_exit("Apt failed to update indexes!")
print("Reading package lists...")
progress(3)
UPDATE_DB = True
return True
############################ Sub-Scripts ############################
def softwareinstall():
print("Installing Pre-requisite Software...This may take a few minutes!")
if not shell.run_command("apt-get install -y libts0", True):
if not shell.run_command("apt-get install -y tslib"):
if not shell.run_command("apt-get install -y libts-dev"):
warn_exit("Apt failed to install TSLIB!")
if not shell.run_command("apt-get install -y bc fbi git python3-dev python3-pip python3-smbus python3-spidev evtest libts-bin device-tree-compiler libraspberrypi-dev build-essential"):
warn_exit("Apt failed to install software!")
if not shell.run_command("pip3 install evdev"):
warn_exit("Pip failed to install software!")
return True
def uninstall_bootconfigtxt():
"""Remove any old flexfb/fbtft stuff"""
if shell.pattern_search("/boot/config.txt", "adafruit-pitft-helper"):
print("Already have an adafruit-pitft-helper section in /boot/config.txt.")
print("Removing old section...")
shell.run_command("cp /boot/config.txt /boot/configtxt.bak")
shell.pattern_replace("/boot/config.txt", '\n# --- added by adafruit-pitft-helper.*?\n# --- end adafruit-pitft-helper.*?\n', multi_line=True)
return True
def update_configtxt():
"""update /boot/config.txt with appropriate values"""
uninstall_bootconfigtxt()
# Driver does not work if hdmi_force_hotplug=1 is present
shell.pattern_replace("/boot/config.txt", "hdmi_force_hotplug=1", "hdmi_force_hotplug=0")
display_overlay = f"dtoverlay=mipi-dbi-spi,{mipi_data['spi']},speed=40000000"
display_overlay += f"\ndtparam=compatible={mipi_data['command_bin']}\\0panel-mipi-dbi-spi"
viewport = ""
if mipi_data['viewport'][pitftrot] is not None:
viewport = mipi_data['viewport'][pitftrot]
display_overlay += f"\ndtparam={viewport}"
if "gpio" in mipi_data:
display_overlay += f"\ndtparam={mipi_data['gpio']}"
# Touch Overlay
touch_overlay = ""
if "touchscreen" in pitft_config and "overlay" in pitft_config["touchscreen"]:
# use dtc to compile and copy overlay
touch_overlay = pitft_config["touchscreen"]["overlay"]
shell.run_command(f"dtc -I dts -O dtb -o /boot/overlays/{touch_overlay}.dtbo overlays/{touch_overlay}.dts")
touch_overlay = f"\ndtoverlay={touch_overlay}"
date = shell.date()
shell.write_text_file("/boot/config.txt", f"""
# --- added by adafruit-pitft-helper {date} ---
[all]
dtparam=spi=on
dtparam=i2c1=on
dtparam=i2c_arm=on
{display_overlay}
{touch_overlay}
# --- end adafruit-pitft-helper {date} ---
""")
return True
def update_udev():
shell.write_text_file("/etc/udev/rules.d/95-touchmouse.rules", """
SUBSYSTEM=="input", ATTRS{name}=="touchmouse", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
""", append=False)
shell.write_text_file("/etc/udev/rules.d/95-ftcaptouch.rules", """
SUBSYSTEM=="input", ATTRS{name}=="EP0110M09", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
SUBSYSTEM=="input", ATTRS{name}=="generic ft5x06*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
""", append=False)
shell.write_text_file("/etc/udev/rules.d/95-stmpe.rules", """
SUBSYSTEM=="input", ATTRS{name}=="*stmpe*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
""", append=False)
return True
def compile_display_fw():
command_src = "mipi/panel.txt"
# We could just copy the file to panel.txt, edit that, then remove it after
shell.copy(f"mipi/{mipi_data['command_bin']}.txt", command_src)
# Make sure each of the lines with "# rotation" starts with exactly 1 # and no more
shell.pattern_replace(command_src, "^#*(.*?# rotation.*?$)", "#\\1")
# Uncomment the one for the rotation we are going for
shell.pattern_replace(command_src, "^#(.*?# rotation " + pitftrot + ".*?$)", "\\1")
# Download the mipi-dbi-cmd script if it doesn't exist
if not shell.exists("mipi-dbi-cmd"):
shell.run_command("wget https://github.com/notro/panel-mipi-dbi/raw/main/mipi-dbi-cmd")
shell.run_command("chmod +x mipi-dbi-cmd")
# Run the mipi-dbi-script and output directly to the /lib/firmware folder
shell.run_command(f"./mipi-dbi-cmd /lib/firmware/{mipi_data['command_bin']}.bin mipi/panel.txt")
shell.remove(command_src)
return True
def update_pointercal():
if "calibrations" in pitft_config["touchscreen"]:
if isinstance(pitft_config["touchscreen"]["calibrations"], dict):
shell.write_text_file("/etc/pointercal", pitft_config["touchscreen"]["calibrations"][pitftrot])
else:
shell.write_text_file("/etc/pointercal", pitft_config["touchscreen"]["calibrations"])
return True
def install_mipi():
global mipi_data
if "mipi_data" in pitft_config:
mipi_data.update(pitft_config['mipi_data'])
if not compile_display_fw():
shell.bail("Unable to compile MIPI firmware")
# if there's X11 installed...
if shell.exists("/etc/lightdm"):
print("Setting raspi-config to boot to desktop w/o login...")
shell.run_command("raspi-config nonint do_boot_behaviour B4")
# Disable overscan compensation (use full screen):
shell.run_command("raspi-config nonint do_overscan 1")
shell.pattern_replace("/boot/config.txt", "^[^#]*dtoverlay=vc4-kms-v3d.*$", "#dtoverlay=vc4-kms-v3d")
shell.pattern_replace("/boot/config.txt", "^[^#]*dtoverlay=vc4-fkms-v3d.*$", "#dtoverlay=vc4-fkms-v3d")
if not update_configtxt():
shell.bail("Unable to update /boot/config.txt")
return True
def update_xorg():
if "touchscreen" in pitft_config:
transform = "Option \"TransformationMatrix\" \"{}\"".format(pitft_config["touchscreen"]["transforms"][pitftrot])
shell.write_text_file("/usr/share/X11/xorg.conf.d/20-calibration.conf", f"""
Section "InputClass"
Identifier "{pitft_config["touchscreen"]["identifier"]}"
MatchProduct "{pitft_config["touchscreen"]["product"]}"
MatchDevicePath "/dev/input/event*"
Driver "libinput"
{transform}
EndSection
""",
append=False,
)
return True
def get_config_types():
types = []
for item in config:
types.append(item["type"])
return types
def get_config(type):
for item in config:
if item["type"] == type:
return item
return None
def success():
global auto_reboot
shell.info("Success!")
print("""
Settings take effect on next boot.
""")
if auto_reboot is None:
auto_reboot = shell.prompt("REBOOT NOW?", default="y")
if not auto_reboot:
print("Exiting without reboot.")
shell.exit()
print("Reboot started...")
shell.reboot()
shell.exit()
####################################################### MAIN
target_homedir = "/home/pi"
@click.command()
@click.option('-v', '--version', is_flag=True, callback=print_version, expose_value=False, is_eager=True, help="Print version information")
@click.option('-u', '--user', nargs=1, default="/home/pi", type=str, help="Specify path of primary user's home directory", show_default=True)
@click.option('--display', nargs=1, default=None, help="Specify a display option (1-{}) or type {}".format(len(config), get_config_types()))
@click.option('--rotation', nargs=1, default=None, type=int, help="Specify a rotation option (1-4) or degrees {}".format(tuple(sorted([int(x) for x in PITFT_ROTATIONS]))))
@click.option('--reboot', nargs=1, default=None, type=click.Choice(['yes', 'no']), help="Specify whether to reboot after the script is finished")
def main(user, display, rotation, reboot):
global target_homedir, pitft_config, pitftrot, auto_reboot
shell.clear()
if user != target_homedir:
target_homedir = user
print("Homedir = {}".format(target_homedir))
print("""This script downloads and installs
PiTFT Support using userspace touch
controls and a DTO for display drawing.
one of several configuration files.
Run time of up to 5 minutes. Reboot required!
""")
if reboot is not None:
auto_reboot = reboot.lower() == 'yes'
# Check that the user is running the minimum kernel on this device
if not shell.kernel_minimum(MIPI_MINIMUM_KERNEL):
shell.warn(f"In order to continue, you will need to update your kernel to a minimum of {MIPI_MINIMUM_KERNEL}. ")
if shell.get_os() == "Raspbian":
shell.info("It looks like you are running this on a Raspberry Pi. You can update it to the latest version by running 'sudo rpi-update'.")
shell.exit()
if display in [str(x) for x in range(1, len(config) + 1)]:
pitft_config = config[int(display) - 1]
print("Display Type: {}".format(pitft_config["menulabel"]))
elif display in get_config_types():
pitft_config = get_config(display)
print("Display Type: {}".format(pitft_config["menulabel"]))
else:
# Build menu from config
selections = []
for item in config:
option = "{} ({}x{})".format(item['menulabel'], item['width'], item['height'])
selections.append(option)
selections.append("Quit without installing")
PITFT_SELECT = shell.select_n("Select configuration:", selections)
if PITFT_SELECT == len(config) + 1:
shell.exit(1)
pitft_config = config[PITFT_SELECT - 1]
if rotation is not None and 1 <= rotation <= 4:
pitftrot = PITFT_ROTATIONS[rotation - 1]
print("Rotation: {}".format(pitftrot))
elif str(rotation) in PITFT_ROTATIONS:
pitftrot = str(rotation)
print("Rotation: {}".format(pitftrot))
else:
PITFT_ROTATE = shell.select_n(
"Select rotation:", (
"90 degrees (landscape)",
"180 degrees (portrait)",
"270 degrees (landscape)",
"0 degrees (portrait)"
))
pitftrot = PITFT_ROTATIONS[PITFT_ROTATE - 1]
if 'rotations' in pitft_config and isinstance(pitft_config['rotations'], dict) and pitftrot in pitft_config['rotations'] and pitft_config['rotations'][pitftrot] is None:
shell.bail("""Unfortunately {rotation} degrees for the {display} is not working at this time. Please
restart the script and choose a different orientation.""".format(rotation=pitftrot, display=pitft_config["menulabel"]))
# check init system (technique borrowed from raspi-config):
shell.info('Checking init system...')
if shell.run_command("which systemctl", True) and shell.run_command("systemctl | grep '\-\.mount'", True):
SYSTEMD = True
print("Found systemd")
elif os.path.isfile("/etc/init.d/cron") and not os.path.islink("/etc/init.d/cron"):
SYSTEMD = False
print("Found sysvinit")
else:
shell.bail("Unrecognised init system")
if shell.grep("boot", "/proc/mounts"):
print("/boot is mounted")
else:
print("/boot must be mounted. if you think it's not, quit here and try: sudo mount /dev/mmcblk0p1 /boot")
if shell.prompt("Continue?"):
print("Proceeding.")
else:
shell.bail("Aborting.")
if not shell.isdir(target_homedir):
shell.bail("{} must be an existing directory (use -u /home/foo to specify)".format(target_homedir))
shell.info("System update")
if not sysupdate():
shell.bail("Unable to apt-get update")
shell.info("Installing Python libraries & Software...")
if not softwareinstall():
shell.bail("Unable to install software")
shell.info("Adding MIPI support...")
if not install_mipi():
shell.bail("Unable to configure mipi")
shell.info("Updating /boot/config.txt...")
if not update_configtxt():
shell.bail("Unable to update /boot/config.txt")
if "touchscreen" in pitft_config:
shell.info("Updating SysFS rules for Touchscreen...")
if not update_udev():
shell.bail("Unable to update /etc/udev/rules.d")
shell.info("Updating TSLib default calibration...")
if not update_pointercal():
shell.bail("Unable to update /etc/pointercal")
if shell.exists("/etc/lightdm"):
shell.info("Updating X11 default calibration...")
if not update_xorg():
shell.bail("Unable to update calibration")
success()
# Main function
if __name__ == "__main__":
shell.require_root()
main()

View file

@ -4,10 +4,11 @@ Adafruit PiTFT Installer Script
"""
import time
import os
try:
import click
except ImportError:
raise RuntimeError("The library 'Click' was not found. To install, try typing: sudo pip3 install Click==7.0")
raise RuntimeError("The library 'Click' was not found. To install, try typing: sudo pip3 install Click")
try:
from adafruit_shell import Shell
except ImportError:
@ -16,7 +17,7 @@ except ImportError:
shell = Shell()
shell.group = 'PITFT'
__version__ = "3.1.1"
__version__ = "3.3.0"
"""
This is the main configuration. Displays should be placed in the order
@ -116,8 +117,8 @@ dtoverlay=pitft28-capacitive,{rotation}""",
"product": "1.54\" or 1.3\" no touch",
"kernel_upgrade": True,
"overlay_src": "overlays/minipitft13-overlay.dts",
"overlay_dest": "/boot/overlays/drm-minipitft13.dtbo",
"overlay": "dtoverlay=drm-minipitft13,rotate={pitftrot},fps=60",
"overlay_dest": "{boot_dir}/overlays/drm-minipitft13.dtbo",
"overlay": "dtoverlay=drm-minipitft13,rotation={pitftrot},fps=60",
"width": 240,
"height": 240,
"fbcp_rotations": {
@ -133,7 +134,7 @@ dtoverlay=pitft28-capacitive,{rotation}""",
"product": "2.0\" no touch",
"kernel_upgrade": True,
"overlay_src": "overlays/st7789v_240x320-overlay.dts",
"overlay_dest": "/boot/overlays/drm-st7789v_240x320.dtbo",
"overlay_dest": "{boot_dir}/overlays/drm-st7789v_240x320.dtbo",
"overlay": "dtoverlay=drm-st7789v_240x320,rotate={pitftrot},fps=30",
"width": 320,
"height": 240,
@ -144,8 +145,8 @@ dtoverlay=pitft28-capacitive,{rotation}""",
"product": "1.14\" no touch",
"kernel_upgrade": True,
"overlay_src": "overlays/minipitft114-overlay.dts",
"overlay_dest": "/boot/overlays/drm-minipitft114.dtbo",
"overlay": "dtoverlay=drm-minipitft114,rotate={pitftrot},fps=60",
"overlay_dest": "{boot_dir}/overlays/drm-minipitft114.dtbo",
"overlay": "dtoverlay=drm-minipitft114,rotation={pitftrot},fps=60",
"rotations": {
"0": None,
"90": "90",
@ -167,8 +168,8 @@ dtoverlay=pitft28-capacitive,{rotation}""",
"product": "1.3\" Joystick",
"kernel_upgrade": True,
"overlay_src": "overlays/tftbonnet13-overlay.dts",
"overlay_dest": "/boot/overlays/drm-tftbonnet13.dtbo",
"overlay": "dtoverlay=drm-tftbonnet13,rotate={pitftrot},fps=60",
"overlay_dest": "{boot_dir}/overlays/drm-tftbonnet13.dtbo",
"overlay": "dtoverlay=drm-tftbonnet13,rotation={pitftrot},fps=60",
"width": 240,
"height": 240,
"fbcp_rotations": {
@ -223,9 +224,9 @@ def sysupdate():
print("Updating apt indexes...", end='')
progress(3)
if not shell.run_command('sudo apt update', True):
warn_exit("Apt failed to update indexes!")
warn_exit("Apt failed to update indexes! Try running 'sudo apt update' manually.")
if not shell.run_command('sudo apt-get update', True):
warn_exit("Apt failed to update indexes!")
warn_exit("Apt failed to update indexes! Try running 'sudo apt-get update' manually.")
print("Reading package lists...")
progress(3)
UPDATE_DB = True
@ -237,7 +238,8 @@ def softwareinstall():
print("Installing Pre-requisite Software...This may take a few minutes!")
if not shell.run_command("apt-get install -y libts0", True):
if not shell.run_command("apt-get install -y tslib"):
warn_exit("Apt failed to install TSLIB!")
if not shell.run_command("apt-get install -y libts-dev"):
warn_exit("Apt failed to install TSLIB!")
if not shell.run_command("apt-get install -y bc fbi git python3-dev python3-pip python3-smbus python3-spidev evtest libts-bin device-tree-compiler libraspberrypi-dev build-essential"):
warn_exit("Apt failed to install software!")
if not shell.run_command("pip3 install evdev"):
@ -246,11 +248,11 @@ def softwareinstall():
def uninstall_bootconfigtxt():
"""Remove any old flexfb/fbtft stuff"""
if shell.pattern_search("/boot/config.txt", "adafruit-pitft-helper"):
print("Already have an adafruit-pitft-helper section in /boot/config.txt.")
if shell.pattern_search(f"{boot_dir}/config.txt", "adafruit-pitft-helper"):
print(f"Already have an adafruit-pitft-helper section in {boot_dir}/config.txt.")
print("Removing old section...")
shell.run_command("cp /boot/config.txt /boot/configtxt.bak")
shell.pattern_replace("/boot/config.txt", '\n# --- added by adafruit-pitft-helper.*?\n# --- end adafruit-pitft-helper.*?\n', multi_line=True)
shell.run_command(f"cp {boot_dir}/config.txt {boot_dir}/configtxt.bak")
shell.pattern_replace(f"{boot_dir}/config.txt", '\n# --- added by adafruit-pitft-helper.*?\n# --- end adafruit-pitft-helper.*?\n', multi_line=True)
return True
def uninstall_etc_modules():
@ -265,7 +267,8 @@ def install_drivers():
"""Compile display driver and overlay if required"""
if "overlay_src" in pitft_config and "overlay_dest" in pitft_config:
print("Compiling Device Tree Overlay")
shell.run_command("dtc --warning no-unit_address_vs_reg -I dts -O dtb -o {dest} {src}".format(dest=pitft_config['overlay_dest'], src=pitft_config['overlay_src']))
destination = pitft_config['overlay_dest'].format(boot_dir=boot_dir)
shell.run_command("dtc --warning no-unit_address_vs_reg -I dts -O dtb -o {dest} {src}".format(dest=destination, src=pitft_config['overlay_src']))
if pitft_config['kernel_upgrade']:
print("############# UPGRADING KERNEL ###############")
@ -290,7 +293,7 @@ def install_drivers():
return True
def update_configtxt(rotation_override=None):
"""update /boot/config.txt with appropriate values"""
"""update /boot/config.txt (or equivalent folder) with appropriate values"""
uninstall_bootconfigtxt()
uninstall_etc_modules()
overlay = pitft_config['overlay']
@ -300,8 +303,9 @@ def update_configtxt(rotation_override=None):
if "{rotation}" in overlay and isinstance(pitft_config['rotations'], dict) and pitft_config['rotations'][pitftrot] is not None:
overlay = overlay.format(rotation=pitft_config['rotations'][pitftrot])
shell.write_text_file("/boot/config.txt", """
shell.write_text_file(f"{boot_dir}/config.txt", """
# --- added by adafruit-pitft-helper {date} ---
[all]
hdmi_force_hotplug=1 # required for cases when HDMI is not plugged in!
dtparam=spi=on
dtparam=i2c1=on
@ -334,11 +338,11 @@ def update_pointercal():
def install_console():
print("Set up main console turn on")
if not shell.pattern_search("/boot/cmdline.txt", 'fbcon=map:10 fbcon=font:VGA8x8'):
print("Updating /boot/cmdline.txt")
shell.pattern_replace("/boot/cmdline.txt", "rootwait", "rootwait fbcon=map:10 fbcon=font:VGA8x8")
if not shell.pattern_search(f"{boot_dir}/cmdline.txt", 'fbcon=map:10 fbcon=font:VGA8x8'):
print(f"Updating {boot_dir}/cmdline.txt")
shell.pattern_replace(f"{boot_dir}/cmdline.txt", "rootwait", "rootwait fbcon=map:10 fbcon=font:VGA8x8")
else:
print("/boot/cmdline.txt already updated")
print(f"{boot_dir}/cmdline.txt already updated")
print("Turning off console blanking")
@ -364,11 +368,11 @@ def install_console():
return True
def uninstall_console():
print("Removing console fbcon map from /boot/cmdline.txt")
shell.pattern_replace("/boot/cmdline.txt", 'rootwait fbcon=map:10 fbcon=font:VGA8x8', 'rootwait')
print(f"Removing console fbcon map from {boot_dir}/cmdline.txt")
shell.pattern_replace(f"{boot_dir}/cmdline.txt", 'rootwait fbcon=map:10 fbcon=font:VGA8x8', 'rootwait')
print("Screen blanking time reset to 10 minutes")
if shell.exists("/etc/kbd/config"):
shell.pattern_replace("/boot/cmdline.txt", 'BLANK_TIME=0', 'BLANK_TIME=10')
shell.pattern_replace(f"{boot_dir}/cmdline.txt", 'BLANK_TIME=0', 'BLANK_TIME=10')
shell.pattern_replace("/etc/rc.local", '^# disable console blanking.*')
shell.pattern_replace("/etc/rc.local", '^sudo sh -c "TERM=linux.*')
return True
@ -429,10 +433,11 @@ def install_fbcp():
shell.run_command("raspi-config nonint do_overscan 1")
# Set up HDMI parameters:
print("Configuring boot/config.txt for forced HDMI")
shell.reconfig("/boot/config.txt", "^.*hdmi_force_hotplug.*$", "hdmi_force_hotplug=1")
shell.reconfig("/boot/config.txt", "^.*hdmi_group.*$", "hdmi_group=2")
shell.reconfig("/boot/config.txt", "^.*hdmi_mode.*$", "hdmi_mode=87")
shell.pattern_replace("/boot/config.txt", "^[^#]*dtoverlay=vc4-fkms-v3d.*$", "#dtoverlay=vc4-fkms-v3d")
shell.reconfig(f"{boot_dir}/config.txt", "^.*hdmi_force_hotplug.*$", "hdmi_force_hotplug=1")
shell.reconfig(f"{boot_dir}/config.txt", "^.*hdmi_group.*$", "hdmi_group=2")
shell.reconfig(f"{boot_dir}/config.txt", "^.*hdmi_mode.*$", "hdmi_mode=87")
shell.pattern_replace(f"{boot_dir}/config.txt", "^[^#]*dtoverlay=vc4-kms-v3d.*$", "#dtoverlay=vc4-kms-v3d")
shell.pattern_replace(f"{boot_dir}/config.txt", "^[^#]*dtoverlay=vc4-fkms-v3d.*$", "#dtoverlay=vc4-fkms-v3d")
# if there's X11 installed...
scale = 1
@ -444,7 +449,7 @@ def install_fbcp():
WIDTH = int(pitft_config['width'] * scale)
HEIGHT = int(pitft_config['height'] * scale)
shell.reconfig("/boot/config.txt", "^.*hdmi_cvt.*$", "hdmi_cvt={} {} 60 1 0 0 0".format(WIDTH, HEIGHT))
shell.reconfig(f"{boot_dir}/config.txt", "^.*hdmi_cvt.*$", "hdmi_cvt={} {} 60 1 0 0 0".format(WIDTH, HEIGHT))
try:
default_orientation = int(list(fbcp_rotations.keys())[list(fbcp_rotations.values()).index("0")])
@ -453,13 +458,13 @@ def install_fbcp():
if fbcp_rotations[pitftrot] == "0":
# dont rotate HDMI on default orientation
shell.reconfig("/boot/config.txt", "^.*display_hdmi_rotate.*$", "")
shell.reconfig(f"{boot_dir}/config.txt", "^.*display_hdmi_rotate.*$", "")
else:
display_rotate = fbcp_rotations[pitftrot]
shell.reconfig("/boot/config.txt", "^.*display_hdmi_rotate.*$", "display_hdmi_rotate={}".format(display_rotate))
shell.reconfig(f"{boot_dir}/config.txt", "^.*display_hdmi_rotate.*$", "display_hdmi_rotate={}".format(display_rotate))
# Because we rotate HDMI we have to 'unrotate' the TFT by overriding pitftrot!
if not update_configtxt(default_orientation):
shell.bail("Unable to update /boot/config.txt")
shell.bail(f"Unable to update {boot_dir}/config.txt")
return True
def install_fbcp_unit():
@ -485,11 +490,12 @@ def uninstall_fbcp():
# Set up HDMI parameters:
shell.run_command("raspi-config nonint do_overscan 0")
print("Configuring boot/config.txt for default HDMI")
shell.reconfig("/boot/config.txt", "^.*hdmi_force_hotplug.*$", "hdmi_force_hotplug=0")
shell.pattern_replace("/boot/config.txt", "^.*#.*dtoverlay=vc4-fkms-v3d.*$", "dtoverlay=vc4-fkms-v3d")
shell.pattern_replace("/boot/config.txt", '^hdmi_group=2.*$')
shell.pattern_replace("/boot/config.txt", '^hdmi_mode=87.*$')
shell.pattern_replace("/boot/config.txt", '^hdmi_cvt=.*$')
shell.reconfig(f"{boot_dir}/config.txt", "^.*hdmi_force_hotplug.*$", "hdmi_force_hotplug=0")
shell.pattern_replace(f"{boot_dir}/config.txt", "^.*#.*dtoverlay=vc4-kms-v3d.*$", "dtoverlay=vc4-kms-v3d")
shell.pattern_replace(f"{boot_dir}/config.txt", "^.*#.*dtoverlay=vc4-fkms-v3d.*$", "dtoverlay=vc4-fkms-v3d")
shell.pattern_replace(f"{boot_dir}/config.txt", '^hdmi_group=2.*$')
shell.pattern_replace(f"{boot_dir}/config.txt", '^hdmi_mode=87.*$')
shell.pattern_replace(f"{boot_dir}/config.txt", '^hdmi_cvt=.*$')
return True
def uninstall_fbcp_rclocal():
@ -556,19 +562,32 @@ Settings take effect on next boot.
####################################################### MAIN
target_homedir = "/home/pi"
username = os.environ["SUDO_USER"]
user_homedir = os.path.expanduser(f"~{username}")
if shell.isdir(user_homedir):
target_homedir = user_homedir
boot_dir = "/boot"
@click.command()
@click.option('-v', '--version', is_flag=True, callback=print_version, expose_value=False, is_eager=True, help="Print version information")
@click.option('-u', '--user', nargs=1, default="/home/pi", type=str, help="Specify path of primary user's home directory", show_default=True)
@click.option('-u', '--user', nargs=1, default=target_homedir, type=str, help="Specify path of primary user's home directory", show_default=True)
@click.option('--display', nargs=1, default=None, help="Specify a display option (1-{}) or type {}".format(len(config), get_config_types()))
@click.option('--rotation', nargs=1, default=None, type=int, help="Specify a rotation option (1-4) or degrees {}".format(tuple(sorted([int(x) for x in PITFT_ROTATIONS]))))
@click.option('--install-type', nargs=1, default=None, type=click.Choice(['fbcp', 'console', 'uninstall']), help="Installation Type")
@click.option('--reboot', nargs=1, default=None, type=click.Choice(['yes', 'no']), help="Specify whether to reboot after the script is finished")
def main(user, display, rotation, install_type, reboot):
global target_homedir, pitft_config, pitftrot, auto_reboot
@click.option('--boot', nargs=1, default="/boot", type=str, help="Specify the boot directory", show_default=True)
def main(user, display, rotation, install_type, reboot, boot):
global target_homedir, pitft_config, pitftrot, auto_reboot, boot_dir
shell.clear()
if user != target_homedir:
target_homedir = user
print("Homedir = {}".format(target_homedir))
print(f"Homedir = {target_homedir}")
if boot != boot_dir:
if shell.isdir(boot):
boot_dir = boot
print(f"Boot dir = {boot_dir}")
else:
print(f"{boot} not found or not a directory. Using {boot_dir} instead.")
print("""This script downloads and installs
PiTFT Support using userspace touch
@ -581,7 +600,7 @@ Run time of up to 5 minutes. Reboot required!
if install_type == "uninstall":
uninstall()
if display in [str(x) for x in range(1, len(config) + 1)]:
pitft_config = config[int(display) - 1]
print("Display Type: {}".format(pitft_config["menulabel"]))
@ -674,9 +693,9 @@ restart the script and choose a different orientation.""".format(rotation=pitftr
if not install_drivers():
shell.bail("Unable to install display drivers")
shell.info("Updating /boot/config.txt...")
shell.info(f"Updating {boot_dir}/config.txt...")
if not update_configtxt():
shell.bail("Unable to update /boot/config.txt")
shell.bail(f"Unable to update {boot_dir}/config.txt")
if "touchscreen" in pitft_config:
shell.info("Updating SysFS rules for Touchscreen...")

View file

@ -31,10 +31,10 @@ forcesudo="no" # whether the script requires to be ran with root privileges
promptreboot="no" # whether the script should always prompt user to reboot
mininstall="no" # whether the script enforces minimum install routine
customcmd="yes" # whether to execute commands specified before exit
armhfonly="yes" # whether the script is allowed to run on other arch
armv6="yes" # whether armv6 processors are supported
armv7="yes" # whether armv7 processors are supported
armv8="yes" # whether armv8 processors are supported
arm64="yes" # whether arm64 processors are supported
raspbianonly="no" # whether the script is allowed to run on other OSes
osreleases=( "Raspbian" ) # list os-releases supported
oswarning=( "Debian" "Kano" "Mate" "PiTop" "Ubuntu" ) # list experimental os-releases
@ -139,9 +139,13 @@ sysreboot() {
}
arch_check() {
IS_ARM64=false
IS_ARMHF=false
IS_ARMv6=false
if uname -m | grep "aarch64" > /dev/null; then
IS_ARM64=true
fi
if uname -m | grep "armv.l" > /dev/null; then
IS_ARMHF=true
if uname -m | grep "armv6l" > /dev/null; then
@ -228,10 +232,12 @@ raspbian_check() {
if [ -f /etc/os-release ]; then
if cat /etc/os-release | grep "/sid" > /dev/null; then
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
elif cat /etc/os-release | grep "bullseye" > /dev/null; then
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
elif cat /etc/os-release | grep "buster" > /dev/null; then
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
elif cat /etc/os-release | grep "stretch" > /dev/null; then
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
elif cat /etc/os-release | grep "jessie" > /dev/null; then
IS_SUPPORTED=true && IS_EXPERIMENTAL=false
elif cat /etc/os-release | grep "wheezy" > /dev/null; then
@ -263,13 +269,16 @@ if [ $debugmode != "no" ]; then
newline
fi
if ! $IS_ARMHF; then
if ! $IS_ARMHF && ! $IS_ARM64; then
warning "This hardware is not supported, sorry!"
warning "Config files have been left untouched"
newline && exit 1
fi
if $IS_ARMv8 && [ $armv8 == "no" ]; then
if $IS_ARM64 && [ $arm64 == "no" ]; then
warning "Sorry, your CPU is not supported by this installer"
newline && exit 1
elif $IS_ARMv8 && [ $armv8 == "no" ]; then
warning "Sorry, your CPU is not supported by this installer"
newline && exit 1
elif $IS_ARMv7 && [ $armv7 == "no" ]; then

View file

@ -17,9 +17,9 @@ I2S microphone support.
print("{} detected.\n".format(pi_model))
if pi_model in ("RASPBERRY_PI_ZERO", "RASPBERRY_PI_ZERO_W"):
pimodel_select = 0
elif pi_model in ("RASPBERRY_PI_2B", "RASPBERRY_PI_3B", "RASPBERRY_PI_3B_PLUS", "RASPBERRY_PI_3A_PLUS"):
elif pi_model in ("RASPBERRY_PI_2B", "RASPBERRY_PI_3B", "RASPBERRY_PI_3B_PLUS", "RASPBERRY_PI_3A_PLUS", "RASPBERRY_PI_ZERO_2_W"):
pimodel_select = 1
elif pi_model in ("RASPBERRY_PI_4B", "RASPBERRY_PI_CM4"):
elif pi_model in ("RASPBERRY_PI_4B", "RASPBERRY_PI_CM4", "RASPBERRY_PI_400"):
pimodel_select = 2
else:
shell.bail("Unsupported Pi board detected.")

View file

@ -0,0 +1,36 @@
# Adafruit HX8257 PiTFT Plus TFT LCD Screen
# width=480,height=320
command 0x01 # _SWRESET and Delay 100ms
delay 100
command 0xB9 0xFF 0x83 0x57 # _SETC and delay 500ms
delay 250
delay 250
command 0xB3 0x80 0x00 0x06 0x06 # _SETRGB 0x80 enables SDO pin (0x00 disables)
command 0xB6 0x25 # _SETCOM -1.52V
command 0xB0 0x68 # _SETOSC Normal mode 70Hz, Idle mode 55 Hz
command 0xCC 0x05 # _SETPANEL BGR, Gate direction swapped
command 0xB1 0x00 0x15 0x1C 0x1C 0x83 0xAA # _SETPWR1 Not deep standby BT VSPR VSNR AP
command 0xC0 0x50 0x50 0x01 0x3C 0x1E 0x08 # _SETSTBA OPON normal OPON idle STBA GEN
command 0xB4 0x02 0x40 0x00 0x2A 0x2A 0x0D 0x78 # _SETCYC NW 0x02 RTN DIV DUM DUM GDON GDOFF
# _SETGAMMA
command 0xE0 0x02 0x0A 0x11 0x1d 0x23 0x35 0x41 0x4b 0x4b 0x42 0x3A 0x27 0x1B 0x08 0x09 0x03 0x02 0x0A 0x11 0x1d 0x23 0x35 0x41 0x4b 0x4b 0x42 0x3A 0x27 0x1B 0x08 0x09 0x03 0x00 0x01
command 0x3A 0x55 # _COLMOD 16 bit
# Command 36h sets the read order from frame memory to the display panel
# Remember to swap width/height on 90/270 rotations
command 0x36 0x00 # rotation 0
#command 0x36 0xA0 # rotation 90
#command 0x36 0xC0 # rotation 180
#command 0x36 0x60 # rotation 270
command 0x35 0x00 # _TEON TW off
command 0x44 0x00 0x02 # _TEARLINE
command 0x11 # _SLPOUT
delay 150
command 0x29 # _DISPON
delay 50

View file

@ -0,0 +1,48 @@
# Adafruit ILI9341 PiTFT TFT LCD Screen
# width=320,height=240
command 0x01 # Software reset
delay 128
command 0xEF 0x03 0x80 0x02
command 0xCF 0x00 0xC1 0x30
command 0xED 0x64 0x03 0x12 0x81
command 0xE8 0x85 0x00 0x78
command 0xCB 0x39 0x2C 0x00 0x34 0x02
command 0xF7 0x20
command 0xEA 0x00 0x00
command 0xc0 0x23 # Power control VRH[5:0]
command 0xc1 0x10 # Power control SAP[2:0];BT[3:0]
command 0xc5 0x3e 0x28 # VCM control
command 0xc7 0x86 # VCM control2
#define MADCTL_MY 0x80 ///< Bottom to top
#define MADCTL_MX 0x40 ///< Right to left
#define MADCTL_MV 0x20 ///< Reverse Mode
#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
#define MADCTL_MH 0x04 ///< LCD refresh right to left
# Command 36h sets the read order from frame memory to the display panel
# Remember to swap width/height on 90/270 rotations
command 0x36 0x88 # rotation 0
#command 0x36 0xE8 # rotation 90
#command 0x36 0x48 # rotation 180
#command 0x36 0x28 # rotation 270
command 0x37 0x00 # Vertical scroll zero
command 0x3a 0x55 # COLMOD: Pixel Format Set
command 0xb1 0x00 0x18 # Frame Rate Control (In Normal Mode/Full Colors)
command 0xb6 0x08 0x82 0x27 # Display Function Control
command 0xF2 0x00 # 3Gamma Function Disable
command 0x26 0x01 # Gamma curve selected
# Set Gamma
command 0xe0 0x0F 0x31 0x2B 0x0C 0x0E 0x08 0x4E 0xF1 0x37 0x07 0x10 0x03 0x0E 0x09 0x00
command 0xe1 0x00 0x0E 0x14 0x03 0x11 0x07 0x31 0xC1 0x48 0x08 0x0F 0x0C 0x31 0x36 0x0F
command 0x11 # Exit Sleep
delay 120
command 0x29 # Display on
delay 120

View file

@ -0,0 +1,29 @@
# Adafruit ST7789 MiniPiTFT LCD and TFT Bonnet
# width=240,height=240
command 0x01 # _SWRESET and Delay 150ms
delay 150
command 0x11 # _SLPOUT and Delay 10ms
delay 10
command 0x3A 0x55 # _COLMOD and Delay 10ms
delay 10
command 0x36 0x08 # _MADCTL Botton->Top Refresh
command 0x21 # _INVON Hack and Delay 10ms
delay 10
command 0x13 # _NORON and Delay 10ms
delay 10
# Command 36h sets the read order from frame memory to the display panel
# Remember to swap width/height on 90/270 rotations if required
command 0x36 0x00 # rotation 0
#command 0x36 0xA0 # rotation 90
#command 0x36 0xC0 # rotation 180
#command 0x36 0x60 # rotation 270
command 0x29 # _DISPON and Delay 500ms
delay 250
delay 250

View file

@ -51,6 +51,7 @@
rotate = <270>;
width = <135>;
height = <240>;
txbuflen = <32768>;
buswidth = <8>;
dc-gpios = <&gpio 25 0>;
led-gpios = <&gpio 26 0>;
@ -59,7 +60,6 @@
};
};
__overrides__ {
speed = <&pitft>,"spi-max-frequency:0";
rotate = <&pitft>,"rotate:0";

View file

@ -51,6 +51,7 @@
rotate = <0>;
width = <240>;
height = <240>;
txbuflen = <32768>;
buswidth = <8>;
dc-gpios = <&gpio 25 0>;
led-gpios = <&gpio 26 0>;

View file

@ -51,6 +51,7 @@
rotate = <0>;
width = <240>;
height = <320>;
txbuflen = <32768>;
buswidth = <8>;
dc-gpios = <&gpio 25 0>;
led-gpios = <&gpio 12 0>;

53
overlays/touch-ft6236.dts Normal file
View file

@ -0,0 +1,53 @@
/*
* Device Tree overlay for the Focaltech FT6236 capacitive
* touch screen controller on the Adafruit PiTFT
*
*/
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
fragment@0 {
target = <&gpio>;
__overlay__ {
pitft_pins: pitft_pins {
brcm,pins = <24>;
brcm,function = <0>; /* in out */
brcm,pull = <2>; /* pullup none */
};
};
};
fragment@1 {
target = <&i2c1>;
__overlay__ {
/* needed to avoid dtc warning */
#address-cells = <1>;
#size-cells = <0>;
ft6236: ft6236@38 {
compatible = "focaltech,ft6236";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pitft_pins>;
interrupt-parent = <&gpio>;
interrupts = <24 2>;
touchscreen-size-x = <240>;
touchscreen-size-y = <320>;
};
};
};
__overrides__ {
touch-sizex = <&ft6236>,"touchscreen-size-x?";
touch-sizey = <&ft6236>,"touchscreen-size-y?";
touch-invx = <&ft6236>,"touchscreen-inverted-x?";
touch-invy = <&ft6236>,"touchscreen-inverted-y?";
touch-swapxy = <&ft6236>,"touchscreen-swapped-x-y?";
};
};

81
overlays/touch-stmpe.dts Normal file
View file

@ -0,0 +1,81 @@
/*
* Device Tree overlay for the STMPE resistive
* touch screen controller on the Adafruit PiTFT
*/
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
fragment@0 {
target = <&spi0>;
__overlay__ {
status = "okay";
};
};
fragment@1 {
target = <&spidev1>;
__overlay__ {
status = "disabled";
};
};
fragment@2 {
target = <&gpio>;
__overlay__ {
pitft_pins: pitft_pins {
brcm,pins = <24>;
brcm,function = <0>; /* in out */
brcm,pull = <2>; /* pullup none */
};
};
};
fragment@3 {
target = <&spi0>;
__overlay__ {
/* needed to avoid dtc warning */
#address-cells = <1>;
#size-cells = <0>;
pitft: pitft_ts@1 {
compatible = "st,stmpe610";
reg = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pitft_pins>;
spi-max-frequency = <500000>;
irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */
interrupts = <24 2>; /* high-to-low edge triggered */
interrupt-parent = <&gpio>;
interrupt-controller;
stmpe_touchscreen {
compatible = "st,stmpe-ts";
st,sample-time = <4>;
st,mod-12b = <1>;
st,ref-sel = <0>;
st,adc-freq = <2>;
st,ave-ctrl = <3>;
st,touch-det-delay = <4>;
st,settling = <2>;
st,fraction-z = <7>;
st,i-drive = <0>;
};
stmpe_gpio: stmpe_gpio {
#gpio-cells = <2>;
compatible = "st,stmpe-gpio";
/*
* only GPIO2 is wired/available
* and it is wired to the backlight
*/
st,norequest-mask = <0x7b>;
};
};
};
};
};

View file

@ -1,30 +1,9 @@
#!/bin/bash
if [ $(id -u) -ne 0 ]; then
echo "Installer must be run as root."
echo "Try 'sudo bash $0'"
exit 1
fi
clear
# smbus and ads1x15 Python libs are installed regardless whether ADC
echo "This script installs software for the Adafruit"
echo "Snake Eyes Bonnet for Raspberry Pi. Steps include:"
echo "- Update package index files (apt-get update)"
echo "- Install Python libraries: numpy, pi3d, svg.path,"
echo " rpi-gpio, python3-dev, python3-pil"
echo "- Install Adafruit eye code and data in /boot"
echo "- Enable SPI0 and SPI1 peripherals if needed"
echo "- Set HDMI resolution, disable overscan"
echo "Run time ~25 minutes. Reboot required."
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
echo
echo -n "CONTINUE? [y/N] "
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
exit 0
echo "Installer must be run as root."
echo "Try 'sudo bash $0'"
exit 1
fi
# FEATURE PROMPTS ----------------------------------------------------------
@ -38,21 +17,60 @@ INSTALL_GADGET=0
# preceded by a number (1 to N), display a prompt, check input until
# a valid number within the selection range is entered.
selectN() {
for ((i=1; i<=$#; i++)); do
echo $i. ${!i}
done
echo
REPLY=""
while :
do
echo -n "SELECT 1-$#: "
read
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
return $REPLY
fi
done
for ((i=1; i<=$#; i++)); do
echo $i. ${!i}
done
echo
REPLY=""
while :
do
echo -n "SELECT 1-$#: "
read
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
return $REPLY
fi
done
}
clear
echo "This script installs Adafruit Snake Eyes Bonnet"
echo "software for Raspberry Pi. It's best to dedicate"
echo "a card to this, not for systems in regular use."
echo
echo "Target system (may be different than current host):"
selectN "Raspberry Pi 4, Pi 400, or Compute Module 4" "All other models"
#if [[ $? -eq "1" ]]; then
if [ $? -eq "1" ]; then
IS_PI4=1
fi
if [ $IS_PI4 ]; then
# Verify this is Raspbian Desktop OS (X11 should exist)
if [ ! -d "/usr/bin/X11" ]; then
echo "Target system is Pi 4/400/CM4 but this appears to"
echo "be a \"Lite\" OS. \"Desktop\" OS is required."
echo -n "Continue anyway? [y/N]"
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
exit 0
fi
fi
else
# Verify this is Raspbian Lite OS (X11 should NOT exist)
if [ -d "/usr/bin/X11" ]; then
echo "Target system is not Pi 4/400/CM4 yet this appears to"
echo "be a \"Desktop\" OS. \"Lite\" OS (Legacy) is required."
echo -n "Continue anyway? [y/N]"
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
exit 0
fi
fi
fi
SCREEN_VALUES=(-o -t -i)
SCREEN_NAMES=("OLED (128x128)" "TFT (128x128)" "IPS (240x240)" HDMI)
RADIUS_VALUES=(128 128 240)
@ -68,40 +86,56 @@ SCREEN_SELECT=$?
echo -n "Install GPIO-halt utility? [y/N] "
read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_HALT=1
echo -n "GPIO pin for halt: "
read
HALT_PIN=$REPLY
INSTALL_HALT=1
echo -n "GPIO pin for halt: "
read
HALT_PIN=$REPLY
fi
echo -n "Install ADC support? [y/N] "
echo -n "Install Bonnet ADC support? [y/N] "
read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_ADC=1
INSTALL_ADC=1
fi
echo -n "Install USB Ethernet gadget support? (Pi Zero) [y/N] "
read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_GADGET=1
INSTALL_GADGET=1
fi
echo
echo "Screen type: ${SCREEN_NAMES[$SCREEN_SELECT-1]}"
if [ $INSTALL_HALT -eq 1 ]; then
echo "Install GPIO-halt: YES (GPIO$HALT_PIN)"
echo "Install GPIO-halt: YES (GPIO$HALT_PIN)"
else
echo "Install GPIO-halt: NO"
echo "Install GPIO-halt: NO"
fi
echo "ADC support: ${OPTION_NAMES[$INSTALL_ADC]}"
echo "Bonnet ADC support: ${OPTION_NAMES[$INSTALL_ADC]}"
echo "Ethernet USB gadget support: ${OPTION_NAMES[$INSTALL_GADGET]}"
if [ $SCREEN_SELECT -eq 3 ]; then
echo "Video resolution will be set to 1280x720, no overscan"
echo "Video resolution will be set to 1280x720, no overscan"
else
echo "Video resolution will be set to 640x480, no overscan"
echo "Video resolution will be set to 640x480, no overscan"
fi
echo
echo -n "CONTINUE? [y/N] "
echo "Installation steps include:"
echo "- Update package index files (apt-get update)"
echo "- Install Python libraries: numpy, pi3d, svg.path,"
echo " rpi-gpio, python3-dev, python3-pil"
echo "- Install Adafruit eye code and data in /boot"
echo "- Set HDMI resolution, GPU RAM, disable overscan"
if [ $IS_PI4 ]; then
echo "- Disable desktop, configure video driver"
fi
echo "- Enable SPI0 and SPI1 peripherals if needed"
echo
echo "THIS IS A ONE-WAY OPERATION, NO UNINSTALL PROVIDED."
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
echo "Run time ~10 minutes. Reboot required."
echo
echo -n "Do you understand and want to proceed? [y/N]"
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
@ -115,26 +149,26 @@ fi
# perform replacement if found, else append replacement to end of file.
# (# $1 = filename, $2 = pattern to match, $3 = replacement)
reconfig() {
grep $2 $1 >/dev/null
if [ $? -eq 0 ]; then
# Pattern found; replace in file
sed -i "s/$2/$3/g" $1 >/dev/null
else
# Not found; append (silently)
echo $3 | sudo tee -a $1 >/dev/null
fi
grep $2 $1 >/dev/null
if [ $? -eq 0 ]; then
# Pattern found; replace in file
sed -i "s/$2/$3/g" $1 >/dev/null
else
# Not found; append (silently)
echo $3 | sudo tee -a $1 >/dev/null
fi
}
# Same as above, but appends to same line rather than new line
reconfig2() {
grep $2 $1 >/dev/null
if [ $? -eq 0 ]; then
# Pattern found; replace in file
sed -i "s/$2/$3/g" $1 >/dev/null
else
# Not found; append to line (silently)
sed -i "s/$/ $3/g" $1 >/dev/null
fi
grep $2 $1 >/dev/null
if [ $? -eq 0 ]; then
# Pattern found; replace in file
sed -i "s/$2/$3/g" $1 >/dev/null
else
# Not found; append to line (silently)
sed -i "s/$/ $3/g" $1 >/dev/null
fi
}
echo
@ -145,8 +179,8 @@ apt-get update
echo "Installing Python libraries..."
# WAS: apt-get install -y --force-yes python-pip python-dev python-imaging python-smbus
apt-get install -y python3-pip python3-dev python3-pil python3-smbus libatlas-base-dev
# WAS: pip3 install numpy pi3d svg.path rpi-gpio adafruit-ads1x15
pip3 install numpy pi3d==2.34 svg.path rpi-gpio adafruit-blinka adafruit-circuitpython-ads1x15
# WAS: pip3 install numpy pi3d==2.34 svg.path rpi-gpio adafruit-ads1x15
pip3 install numpy pi3d svg.path rpi-gpio adafruit-blinka adafruit-circuitpython-ads1x15
# smbus and Blinka+ADC libs are installed regardless whether ADC is
# enabled; simplifies the Python code a little (no "uncomment this")
@ -158,110 +192,165 @@ unzip master.zip
cp -r Pi_Eyes-master /boot/Pi_Eyes
rm -rf master.zip Pi_Eyes-master
if [ $INSTALL_HALT -ne 0 ]; then
echo "Installing gpio-halt in /usr/local/bin..."
curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
unzip master.zip
cd Adafruit-GPIO-Halt-master
make
mv gpio-halt /usr/local/bin
cd ..
rm -rf Adafruit-GPIO-Halt-master
echo "Installing gpio-halt in /usr/local/bin..."
curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
unzip master.zip
cd Adafruit-GPIO-Halt-master
make
mv gpio-halt /usr/local/bin
cd ..
rm -rf Adafruit-GPIO-Halt-master
fi
# CONFIG -------------------------------------------------------------------
echo "Configuring system..."
if [ $IS_PI4 ]; then
# Make desktop system to boot to console (from raspi-config script):
systemctl set-default multi-user.target
ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
# Pi3D requires "fake" KMS overlay to work. Check /boot/config.txt for
# vc4-fkms-v3d overlay present and active. If so, nothing to do here,
# module's already configured.
grep '^dtoverlay=vc4-fkms-v3d' /boot/config.txt >/dev/null
if [ $? -ne 0 ]; then
# fkms overlay not present, or is commented out. Check if vc4-kms-v3d
# (no 'f') is present and active. That's normally the default.
grep '^dtoverlay=vc4-kms-v3d' /boot/config.txt >/dev/null
if [ $? -eq 0 ]; then
# It IS present. Comment out that line for posterity, and insert the
# 'fkms' item on the next line.
sed -i "s/^dtoverlay=vc4-kms-v3d/#&\ndtoverlay=vc4-fkms-v3d/g" /boot/config.txt >/dev/null
else
# It's NOT present. Silently append 'fkms' overlay to end of file.
echo dtoverlay=vc4-fkms-v3d | sudo tee -a /boot/config.txt >/dev/null
fi
fi
# Disable screen blanking in X config
echo "Section \"ServerFlags\"
Option \"BlankTime\" \"0\"
Option \"StandbyTime\" \"0\"
Option \"SuspendTime\" \"0\"
Option \"OffTime\" \"0\"
Option \"dpms\" \"false\"
EndSection" > /etc/X11/xorg.conf
fi
# Disable overscan compensation (use full screen):
raspi-config nonint do_overscan 1
# Dedicate 128 MB to the GPU:
sudo raspi-config nonint do_memory_split 128
# HDMI settings for Pi eyes
reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
if [ $SCREEN_SELECT -eq 3 ]; then
# IPS display - set HDMI to 1280x720
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
# IPS display - set HDMI to 1280x720
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
else
# All others - set HDMI to 640x480
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
# All others - set HDMI to 640x480
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
fi
# Enable I2C for ADC
if [ $INSTALL_ADC -ne 0 ]; then
raspi-config nonint do_i2c 0
raspi-config nonint do_i2c 0
fi
if [ $INSTALL_HALT -ne 0 ]; then
# Add gpio-halt to /rc.local:
grep gpio-halt /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# gpio-halt already in rc.local, but make sure correct:
sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
else
# Insert gpio-halt into rc.local before final 'exit 0'
sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
# Add gpio-halt to /rc.local:
grep gpio-halt /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# gpio-halt already in rc.local, but make sure correct:
sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
else
# Insert gpio-halt into rc.local before final 'exit 0'
sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
fi
# If using OLED, TFT or IPS, enable SPI and install fbx2 and eyes.py,
# else (HDMI) skip SPI, fbx2 and install cyclops.py (single eye)
if [ $SCREEN_SELECT -ne 4 ]; then
# Enable SPI0 using raspi-config
raspi-config nonint do_spi 0
# Enable SPI0 using raspi-config
raspi-config nonint do_spi 0
# Enable SPI1 by adding overlay to /boot/config.txt
reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
# Enable SPI1 by adding overlay to /boot/config.txt
reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
# Adjust spidev buffer size to 8K (default is 4K)
reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
# Adjust spidev buffer size to 8K (default is 4K)
reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
# Auto-start fbx2 on boot
grep fbx2 /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# fbx2 already in rc.local, but make sure correct:
sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
else
# Insert fbx2 into rc.local before final 'exit 0'
sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
# Auto-start fbx2 on boot
grep fbx2 /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# fbx2 already in rc.local, but make sure correct:
sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
else
# Insert fbx2 into rc.local before final 'exit 0'
sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
# Auto-start eyes.py on boot
grep eyes.py /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# eyes.py already in rc.local, but make sure correct:
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
else
# Insert eyes.py into rc.local before final 'exit 0'
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
# Auto-start eyes.py on boot
grep eyes.py /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# eyes.py already in rc.local, but make sure correct:
if [ $IS_PI4 ]; then
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 eyes.py --radius $RADIUS \:0 \&/g" /etc/rc.local >/dev/null
else
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
fi
else
# Insert eyes.py into rc.local before final 'exit 0'
if [ $IS_PI4 ]; then
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 eyes.py --radius $RADIUS \:0 \&\\nexit 0/g" /etc/rc.local >/dev/null
else
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
fi
else
# Auto-start cyclops.py on boot
grep cyclops.py /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# cyclops.py already in rc.local, but make sure correct:
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python3 cyclops.py \&/g" /etc/rc.local >/dev/null
else
# Insert cyclops.py into rc.local before final 'exit 0'
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
# Auto-start cyclops.py on boot
grep cyclops.py /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then
# cyclops.py already in rc.local, but make sure correct:
if [ $IS_PI4 ]; then
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 cyclops.py \:0 \&/g" /etc/rc.local >/dev/null
else
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python3 cyclops.py \&/g" /etc/rc.local >/dev/null
fi
else
# Insert cyclops.py into rc.local before final 'exit 0'
if [ $IS_PI4 ]; then
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 cyclops.py \:0 \&\\nexit 0/g" /etc/rc.local >/dev/null
else
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
fi
fi
if [ $INSTALL_GADGET -ne 0 ]; then
reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
if [ $? -ne 0 ]; then
# Insert ethernet gadget into config.txt after 'rootwait'
sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
fi
reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
if [ $? -ne 0 ]; then
# Insert ethernet gadget into config.txt after 'rootwait'
sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
fi
fi
# PROMPT FOR REBOOT --------------------------------------------------------
@ -273,8 +362,8 @@ echo
echo -n "REBOOT NOW? [y/N] "
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Exiting without reboot."
exit 0
echo "Exiting without reboot."
exit 0
fi
echo "Reboot started..."
reboot

View file

@ -17,7 +17,10 @@ blinka_minimum_python_version = 3.6
def default_python_version(numeric=True):
version = shell.run_command("python -c 'import platform; print(platform.python_version())'", suppress_message=True, return_output=True)
if numeric:
return float(version[0:version.rfind(".")])
try:
return float(version[0:version.rfind(".")])
except ValueError:
return None
return version
def get_python3_version(numeric=True):
@ -33,10 +36,10 @@ def check_blinka_python_version():
print("Making sure the required version of Python is installed")
if get_python3_version() < blinka_minimum_python_version:
shell.bail("Blinka requires a minimum of Python version {} to install. Please update your OS!".format(blinka_minimum_python_version))
def sys_update():
print("Updating System Packages")
if not shell.run_command("sudo apt-get update"):
if not shell.run_command("sudo apt-get update --allow-releaseinfo-change"):
shell.bail("Apt failed to update indexes!")
print("Upgrading packages...")
if not shell.run_command("sudo apt-get -y upgrade"):
@ -74,7 +77,7 @@ def update_pip():
def install_blinka():
print("Installing latest version of Blinka locally")
shell.run_command("sudo apt-get install -y i2c-tools")
shell.run_command("sudo apt-get install -y i2c-tools libgpiod-dev")
shell.run_command("pip3 install --upgrade RPi.GPIO")
shell.run_command("pip3 install --upgrade adafruit-blinka")
@ -89,12 +92,19 @@ Raspberry Pi and installs Blinka
print("{} detected.\n".format(pi_model))
if not shell.is_raspberry_pi():
shell.bail("Non-Raspberry Pi board detected. This must be run on a Raspberry Pi")
if shell.get_os() != "Raspbian":
shell.bail("Sorry. This script currently only runs on Raspberry Pi OS.")
os_identifier = shell.get_os()
if os_identifier != "Raspbian":
shell.bail("Sorry, the OS detected was {}. This script currently only runs on Raspberry Pi OS.".format(os_identifier))
if not shell.is_python3():
shell.bail("You must be running Python 3. Older versions have now been deprecated.")
shell.check_kernel_update_reboot_required()
if default_python_version() < 3:
python_version = default_python_version()
if not python_version:
shell.warn("WARNING No Default System python tied to the `python` command. It will be set to Version 3.")
default_python = 0
if not shell.prompt("Continue?"):
shell.exit()
elif default_python_version() < 3:
shell.warn("WARNING Default System python version is {}. It will be updated to Version 3.".format(default_python_version(False)))
default_python = 2
if not shell.prompt("Continue?"):

144
raspi-spi-reassign.py Normal file
View file

@ -0,0 +1,144 @@
"""
Adafruit Raspberry Pi SPI Chip Enable Reassignment Script
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
"""
try:
import click
except ImportError:
raise RuntimeError("The library 'Click' was not found. To install, try typing: sudo pip3 install Click")
try:
from adafruit_shell import Shell
except ImportError:
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
import os
shell = Shell()
shell.group="SPI Reassign"
allowed_gpios = (4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27)
spi0_default_pins = (8, 7)
"""
For now this will only ask about SPI0, but we can later add SPI1
"""
def valid_pins(ce0_pin, ce1_pin):
if ce0_pin is None or ce1_pin is None:
return False
if ce0_pin == ce1_pin:
return False
if int(ce0_pin) not in allowed_gpios:
return False
if int(ce1_pin) not in allowed_gpios:
return False
return True
def disable_spi():
print("Disabling SPI")
shell.run_command("sudo raspi-config nonint do_spi 1")
def enable_spi():
print("Enabling SPI")
shell.run_command("sudo raspi-config nonint do_spi 0")
def remove_custom():
shell.pattern_replace("/boot/config.txt", 'dtoverlay=spi0-2cs,cs.*?\n', multi_line=True)
def write_new_custom(ce0_pin, ce1_pin):
if (ce0_pin, ce1_pin) == spi0_default_pins:
enable_spi()
else:
overlay_command = "dtoverlay=spi0-2cs"
if ce0_pin != spi0_default_pins[0]:
overlay_command += ",cs0_pin={}".format(ce0_pin)
if ce1_pin != spi0_default_pins[1]:
overlay_command += ",cs1_pin={}".format(ce1_pin)
shell.write_text_file("/boot/config.txt", overlay_command + "\n")
@click.command()
@click.option('--ce0', nargs=1, default=None, help="Specify a GPIO for CE0")
@click.option('--ce1', nargs=1, default=None, help="Specify a GPIO for CE1")
@click.option('--reboot', nargs=1, default=None, type=click.Choice(['yes', 'no']), help="Specify whether to reboot after the script is finished")
def main(ce0, ce1, reboot):
ask_reboot = True
auto_reboot = False
if reboot is not None:
ask_reboot = False
auto_reboot = reboot.lower() == 'yes'
if valid_pins(ce0, ce1):
remove_custom()
disable_spi()
write_new_custom(ce0, ce1)
if auto_reboot:
shell.reboot()
if ask_reboot:
shell.prompt_reboot()
exit(0)
else:
print("Invalid ce0 or ce1", ce0, ce1)
#shell.clear()
# Check Raspberry Pi and Bail
pi_model = shell.get_board_model()
print("""This script allows you
to easily reassign the SPI Chip Enable
pins so the OS automatic handling of the
lines doesn't interfere with CircuitPython.
Run time of < 1 minute. Reboot required for
changes to take effect!
""")
shell.info("{} detected.\n".format(pi_model))
if not shell.is_raspberry_pi():
shell.bail("Non-Raspberry Pi board detected. This must be run on a Raspberry Pi")
os_identifier = shell.get_os()
if os_identifier != "Raspbian":
shell.bail("Sorry, the OS detected was {}. This script currently only runs on Raspberry Pi OS.".format(os_identifier))
menu_selection = shell.select_n(
"Select an option:", (
"Reassign SPI Chip Enable Pins",
"Reset to Defaults Pins",
"Disable SPI",
"Exit",
)
)
if menu_selection == 1:
while True:
# Reassign
gpio_pool = list(allowed_gpios)
# Ask for pin for CE0
ce0_selection = shell.select_n("Select a new GPIO for CE0", ["GPIO {}".format(x) for x in gpio_pool])
ce0_pin = gpio_pool[ce0_selection - 1]
gpio_pool.remove(ce0_pin)
# Ask for pin for CE1
ce1_selection = shell.select_n("Select a new GPIO for CE1", ["GPIO {}".format(x) for x in gpio_pool])
ce1_pin = gpio_pool[ce1_selection - 1]
if shell.prompt("The new GPIO {} for CE0 and GPIO {} for CE1. Is this correct?".format(ce0_pin, ce1_pin)):
break
remove_custom()
disable_spi()
write_new_custom(ce0_pin, ce1_pin)
elif menu_selection == 2:
# Reset to Defaults
remove_custom()
enable_spi()
elif menu_selection == 3:
# Disable
remove_custom()
disable_spi()
elif menu_selection == 4:
# Exit
shell.exit(0)
# Done
print("""DONE.
Settings take effect on next boot.
""")
if auto_reboot:
shell.reboot()
if ask_reboot:
shell.prompt_reboot()
# Main function
if __name__ == "__main__":
shell.require_root()
main()

View file

@ -1,5 +1,11 @@
#!/bin/bash
echo "NEWS: see https://learn.adafruit.com/read-only-raspberry-pi"
echo "This script is deprecated, with better functionality now in"
echo "the OS without hacks. It's being kept temporarily for reference."
echo "You can edit this part out if you really need to run it."
exit 0
# CREDIT TO THESE TUTORIALS:
# petr.io/en/blog/2015/11/09/read-only-raspberry-pi-with-jessie
# hallard.me/raspberry-pi-read-only
@ -284,18 +290,23 @@ replace /usr/lib/tmpfiles.d/var.conf "spool\s*0755" "spool 1777"
touch /tmp/dhcpcd.resolv.conf
rm /etc/resolv.conf
ln -s /tmp/dhcpcd.resolv.conf /etc/resolv.conf
# systemd-ntp must use systemwide /tmp to access /tmp/dhcpcd.resolv.conf
replace /lib/systemd/system/ntp.service "PrivateTmp=true" "PrivateTmp=false"
# Make edits to fstab
# make / ro
# tmpfs /var/log tmpfs nodev,nosuid 0 0
# tmpfs /var/tmp tmpfs nodev,nosuid 0 0
# tmpfs /tmp tmpfs nodev,nosuid 0 0
replace /etc/fstab "vfat\s*defaults\s" "vfat defaults,ro "
replace /etc/fstab "ext4\s*defaults,noatime\s" "ext4 defaults,noatime,ro "
replace /etc/fstab "vfat\s*defaults\s.*" "vfat defaults,ro\t0\t0"
replace /etc/fstab "ext4\s*defaults,noatime\s.*" "ext4 defaults,noatime,ro\t0\t0"
append1 /etc/fstab "/var/log" "tmpfs /var/log tmpfs nodev,nosuid 0 0"
append1 /etc/fstab "/var/tmp" "tmpfs /var/tmp tmpfs nodev,nosuid 0 0"
append1 /etc/fstab "\s/tmp" "tmpfs /tmp tmpfs nodev,nosuid 0 0"
# Stop vim creating tmp files in ~/.viminfo (ro)
echo 'set viminfo=""' >>/etc/vim/vimrc.local
# PROMPT FOR REBOOT --------------------------------------------------------
echo "Done."

View file

@ -7,7 +7,8 @@
# we reference a specific commit (update this as needed):
GITUSER=https://github.com/hzeller
REPO=rpi-rgb-led-matrix
COMMIT=21410d2b0bac006b4a1661594926af347b3ce334
COMMIT=45d3ab5d6cff6e0c14da58930d662822627471fc #needs updated if This is merged/Released
# Previously: COMMIT=21410d2b0bac006b4a1661594926af347b3ce334
# Previously: COMMIT=e3dd56dcc0408862f39cccc47c1d9dea1b0fb2d2
if [ $(id -u) -ne 0 ]; then
@ -16,6 +17,9 @@ if [ $(id -u) -ne 0 ]; then
exit 1
fi
HAS_PYTHON2=$( [ ! $(which python2) ] ; echo $?)
HAS_PYTHON3=$( [ ! $(which python3) ] ; echo $?)
clear
echo "This script installs software for the Adafruit"
@ -28,10 +32,10 @@ echo "- Configure boot options"
echo "Run time ~15 minutes. Some options require reboot."
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
echo
echo -n "CONTINUE? [y/N] "
echo -n "CONTINUE? [y/n] "
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
echo "Canceled. "
exit 0
fi
@ -111,7 +115,7 @@ INTERFACE_TYPE=$?
if [ $INTERFACE_TYPE -eq 1 ]; then
# For matrix HAT, ask about RTC install
echo
echo -n "Install realtime clock support? [y/N] "
echo -n "Install realtime clock support? [y/n] "
read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_RTC=1
@ -174,10 +178,10 @@ if [ $QUALITY_MOD -eq 0 ]; then
echo "and GPIO18, and internal sound is DISABLED!"
fi
echo
echo -n "CONTINUE? [y/N] "
echo -n "CONTINUE? [y/n] "
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
echo "Canceled. "
exit 0
fi
@ -204,7 +208,12 @@ echo "Updating package index files..."
apt-get update
echo "Downloading prerequisites..."
apt-get install -y --force-yes python2.7-dev python-pillow python3-dev python3-pillow
if [ $HAS_PYTHON2 ]; then
apt-get install -y --force-yes python2.7-dev python-pillow
fi
if [ $HAS_PYTHON3 ]; then
apt-get install -y --force-yes python3-dev python3-pillow
fi
echo "Downloading RGB matrix software..."
curl -L $GITUSER/$REPO/archive/$COMMIT.zip -o $REPO-$COMMIT.zip
@ -222,20 +231,28 @@ USER_DEFINES=""
# USER_DEFINES+=" -DLED_ROWS=${MATRIX_HEIGHTS[$MATRIX_SIZE]}"
#fi
if [ $QUALITY_MOD -eq 0 ]; then
# Build and install for Python 2.7...
make clean
make install-python HARDWARE_DESC=adafruit-hat-pwm USER_DEFINES="$USER_DEFINES" PYTHON=$(which python2)
# Do over for Python 3...
make clean
make install-python HARDWARE_DESC=adafruit-hat-pwm USER_DEFINES="$USER_DEFINES" PYTHON=$(which python3)
if [ $HAS_PYTHON2 ]; then
# Build and install for Python 2.7...
make clean
make install-python HARDWARE_DESC=adafruit-hat-pwm USER_DEFINES="$USER_DEFINES" PYTHON=$(which python2)
fi
if [ $HAS_PYTHON3 ]; then
# Do over for Python 3...
make clean
make install-python HARDWARE_DESC=adafruit-hat-pwm USER_DEFINES="$USER_DEFINES" PYTHON=$(which python3)
fi
else
# Build then install for Python 2.7...
USER_DEFINES+=" -DDISABLE_HARDWARE_PULSES"
make clean
make install-python HARDWARE_DESC=adafruit-hat USER_DEFINES="$USER_DEFINES" PYTHON=$(which python2)
# Do over for Python 3...
make clean
make install-python HARDWARE_DESC=adafruit-hat USER_DEFINES="$USER_DEFINES" PYTHON=$(which python3)
if [ $HAS_PYTHON2 ]; then
# Build then install for Python 2.7...
make clean
make install-python HARDWARE_DESC=adafruit-hat USER_DEFINES="$USER_DEFINES" PYTHON=$(which python2)
fi
if [ $HAS_PYTHON3 ]; then
# Do over for Python 3...
make clean
make install-python HARDWARE_DESC=adafruit-hat USER_DEFINES="$USER_DEFINES" PYTHON=$(which python3)
fi
fi
# Change ownership to user calling sudo
chown -R $SUDO_USER:$(id -g $SUDO_USER) `pwd`
@ -272,14 +289,15 @@ echo "Settings take effect on next boot."
if [ $INSTALL_RTC -ne 0 ]; then
echo "RTC will be enabled then but time must be set"
echo "up using the 'date' and 'hwclock' commands."
echo "ref: https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/set-rtc-time#sync-time-from-pi-to-rtc"
fi
echo
echo -n "REBOOT NOW? [y/N] "
echo -n "REBOOT NOW? [y/n] "
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Exiting without reboot."
exit 0
fi
echo "Reboot started..."
echo "Reboot process started..."
reboot
sleep infinity

View file

@ -22,12 +22,13 @@ if [ `id -u` -ne 0 ]; then
fi
version=$1
fileversion=$(echo $version | cut -d':' -f 2)
base=http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/
packagelist="libraspberrypi0 libraspberrypi-bin libraspberrypi-dev libraspberrypi-doc raspberrypi-bootloader raspberrypi-kernel raspberrypi-kernel-headers"
set --
for package in $packagelist; do
filename="${package}_${version}_armhf.deb"
filename="${package}_${fileversion}_armhf.deb"
set -- "$@" "$filename"
wget --continue -O "$filename" "$base/$filename"
done
@ -35,5 +36,5 @@ done
dpkg -i "$@"
for package in $packagelist; do
/usr/bin/printf "Package: $package\nPin: version 1.20201126-1\nPin-Priority:999\n\n"
/usr/bin/printf "Package: $package\nPin: version ${version}\nPin-Priority:999\n\n"
done > /etc/apt/preferences.d/99-adafruit-pin-kernel