From 005932736e907ef86ff77c85ac1a1a3ac35ff49c Mon Sep 17 00:00:00 2001 From: "Limor \"Ladyada\" Fried" Date: Sun, 11 Feb 2018 20:22:06 -0500 Subject: [PATCH] Create adafruit-pitft.sh --- adafruit-pitft.sh | 591 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 591 insertions(+) create mode 100644 adafruit-pitft.sh diff --git a/adafruit-pitft.sh b/adafruit-pitft.sh new file mode 100644 index 0000000..26e16d3 --- /dev/null +++ b/adafruit-pitft.sh @@ -0,0 +1,591 @@ +#!/bin/bash + +# Instructions! +# cd ~ +# wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/adafruit-pitft.sh +# chmod +x adafruit-pitft.sh +# sudo ./adafruit-pitft.sh + +if [ $(id -u) -ne 0 ]; then + echo "Installer must be run as root." + echo "Try 'sudo bash $0'" + exit 1 +fi + + +UPDATE_DB=false + +############################ Script assisters ############################ + +# Given a list of strings representing options, display each option +# 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 +} + + +function print_version() { + echo "Adafruit PiTFT Helper v2.0.0" + exit 1 +} + +function print_help() { + echo "Usage: $0 " + echo " -h Print this help" + echo " -v Print version information" + echo " -u [homedir] Specify path of primary user's home directory (defaults to /home/pi)" + exit 1 +} + +group=ADAFRUIT +function info() { + system="$1" + group="${system}" + shift + FG="1;32m" + BG="40m" + echo -e "[\033[${FG}\033[${BG}${system}\033[0m] $*" +} + +function bail() { + FG="1;31m" + BG="40m" + echo -en "[\033[${FG}\033[${BG}${group}\033[0m] " + if [ -z "$1" ]; then + echo "Exiting due to error" + else + echo "Exiting due to error: $*" + fi + exit 1 +} + +function ask() { + # http://djm.me/ask + while true; do + + if [ "${2:-}" = "Y" ]; then + prompt="Y/n" + default=Y + elif [ "${2:-}" = "N" ]; then + prompt="y/N" + default=N + else + prompt="y/n" + default= + fi + + # Ask the question + read -p "$1 [$prompt] " REPLY + + # Default? + if [ -z "$REPLY" ]; then + REPLY=$default + fi + + # Check if the reply is valid + case "$REPLY" in + Y*|y*) return 0 ;; + N*|n*) return 1 ;; + esac + done +} + + +progress() { + count=0 + until [ $count -eq $1 ]; do + echo -n "..." && sleep 1 + ((count++)) + done + echo +} + +sysupdate() { + if ! $UPDATE_DB; then + echo "Updating apt indexes..." && progress 3 & + sudo apt-get update 1> /dev/null || { warning "Apt failed to update indexes!" && exit 1; } + echo "Reading package lists..." + progress 3 && UPDATE_DB=true + fi +} + + +# Given a filename, a regex pattern to match and a replacement string, +# 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 +} + + +############################ Sub-Scripts ############################ + +function softwareinstall() { + echo "Installing Pre-requisite Software...This may take a few minutes!" + apt-get install -y bc fbi git python-pip python-smbus python-spidev evtest tslib libts-bin 1> /dev/null || { warning "Apt failed to install software!" && exit 1; } + pip install evdev 1> /dev/null || { warning "Pip failed to install software!" && exit 1; } +} + +# update /boot/config.txt with appropriate values +function update_configtxt() { + if grep -q "adafruit-pitft-helper" "/boot/config.txt"; then + echo "Already have an adafruit-pitft-helper section in /boot/config.txt." + echo "Removing old section..." + cp /boot/config.txt /boot/configtxt.bak + sed -i -e "/^# --- added by adafruit-pitft-helper/,/^# --- end adafruit-pitft-helper/d" /boot/config.txt + fi + + if [ "${pitfttype}" == "22" ]; then + overlay="dtoverlay=pitft22,rotate=${pitftrot},speed=64000000,fps=30" + fi + + if [ "${pitfttype}" == "28r" ]; then + overlay="dtoverlay=pitft28-resistive,rotate=${pitftrot},speed=64000000,fps=30" + fi + + if [ "${pitfttype}" == "28c" ]; then + overlay="dtoverlay=pitft28-capacitive,rotate=${pitftrot},speed=64000000,fps=30" + fi + + if [ "${pitfttype}" == "35r" ]; then + overlay="dtoverlay=pitft35-resistive,rotate=${pitftrot},speed=20000000,fps=20" + fi + + + date=`date` + + cat >> /boot/config.txt < /etc/udev/rules.d/95-touchmouse.rules < /etc/udev/rules.d/95-ftcaptouch.rules < /etc/udev/rules.d/95-stmpe.rules < /etc/pointercal < /etc/pointercal < /etc/pointercal < /etc/pointercal < /etc/pointercal < /etc/pointercal < /etc/pointercal < /etc/pointercal < /etc/pointercal </dev/tty0\"\\nexit 0|" /etc/rc.local + + reconfig /etc/default/console-setup "^.*FONTFACE.*$" "FONTFACE=\"Terminus\"" + reconfig /etc/default/console-setup "^.*FONTSIZE.*$" "FONTSIZE=\"6x12\"" + + echo "Setting raspi-config to boot to console w/o login..." + raspi-config nonint do_boot_behaviour B2 + + # remove fbcp + sed -i -e "/^.*fbcp.*$/d" /etc/rc.local +} + + +function uninstall_console() { + echo "Removing console fbcon map from /boot/cmdline.txt" + sed -i 's/rootwait fbcon=map:10 fbcon=font:VGA8x8/rootwait/g' "/boot/cmdline.txt" + echo "Screen blanking time reset to 10 minutes" + if [ -e "/etc/kbd/config" ]; then + sed -i 's/BLANK_TIME=0/BLANK_TIME=10/g' "/etc/kbd/config" + fi + sed -i -e '/^# disable console blanking.*/d' /etc/rc.local + sed -i -e '/^sudo sh -c "TERM=linux.*/d' /etc/rc.local +} + +function install_fbcp() { + echo "Installing cmake..." + apt-get --yes --force-yes install cmake 1> /dev/null || { warning "Apt failed to install software!" && exit 1; } + echo "Downloading rpi-fbcp..." + cd /tmp + #curl -sLO https://github.com/tasanakorn/rpi-fbcp/archive/master.zip + curl -sLO https://github.com/adafruit/rpi-fbcp/archive/master.zip + echo "Uncompressing rpi-fbcp..." + rm -rf /tmp/rpi-fbcp-master + unzip master.zip 1> /dev/null || { warning "Failed to uncompress fbcp!" && exit 1; } + cd rpi-fbcp-master + mkdir build + cd build + echo "Building rpi-fbcp..." + cmake .. 1> /dev/null || { warning "Failed to cmake fbcp!" && exit 1; } + make 1> /dev/null || { warning "Failed to make fbcp!" && exit 1; } + echo "Installing rpi-fbcp..." + install fbcp /usr/local/bin/fbcp + rm -rf /tmp/rpi-fbcp-master + + # Add fbcp to /rc.local: + echo "Add fbcp to /etc/rc.local..." + grep fbcp /etc/rc.local >/dev/null + if [ $? -eq 0 ]; then + # fbcp already in rc.local, but make sure correct: + sed -i "s|^.*fbcp.*$|/usr/local/bin/fbcp \&|g" /etc/rc.local >/dev/null + else + #Insert fbcp into rc.local before final 'exit 0' + sed -i "s|^exit 0|/usr/local/bin/fbcp \&\\nexit 0|g" /etc/rc.local >/dev/null + fi + # if there's X11 installed... + if [ -e /etc/lightdm ]; then + echo "Setting raspi-config to boot to desktop w/o login..." + raspi-config nonint do_boot_behaviour B4 + fi + # Disable overscan compensation (use full screen): + raspi-config nonint do_overscan 1 + # Set up HDMI parameters: + echo "Configuring boot/config.txt for forced HDMI" + 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 there's X11 installed... + if [ -e /etc/lightdm ]; then + if [ "${pitfttype}" == "35r" ]; then + echo "Using x1.5 resolution" + SCALE=1.5 + else + echo "Using x2 resolution" + SCALE=2.0 + fi + else + echo "Using native resolution" + SCALE=1 + fi + WIDTH=`python -c "print(int(${WIDTH_VALUES[PITFT_SELECT-1]} * ${SCALE}))"` + HEIGHT=`python -c "print(int(${HEIGHT_VALUES[PITFT_SELECT-1]} * ${SCALE}))"` + reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=${WIDTH} ${HEIGHT} 60 1 0 0 0" + +} + +function uninstall_fbcp() { + # Remove fbcp from /etc/rc.local: + echo "Remove fbcp from /etc/rc.local..." + sed -i -e '/^.*fbcp.*$/d' /etc/rc.local + + # Enable overscan compensation + raspi-config nonint do_overscan 0 + # Set up HDMI parameters: + echo "Configuring boot/config.txt for default HDMI" + reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=0" + sed -i -e '/^hdmi_group=2.*$/d' /boot/config.txt + sed -i -e '/^hdmi_mode=87.*$/d' /boot/config.txt + sed -i -e '/^hdmi_cvt=.*$/d' /boot/config.txt +} + +# currently for '90' rotation only +function update_xorg() { + if [ "${pitfttype}" == "28r" ]; then + cat > /usr/share/X11/xorg.conf.d/20-calibration.conf < /usr/share/X11/xorg.conf.d/20-calibration.conf < /usr/share/X11/xorg.conf.d/20-calibration.conf < /dev/null && systemctl | grep -q '\-\.mount'; then + echo "Found systemd" + SYSTEMD=1 +elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then + echo "Found sysvinit" + SYSTEMD=0 +else + bail "Unrecognised init system" +fi + +if grep -q boot /proc/mounts; then + echo "/boot is mounted" +else + echo "/boot must be mounted. if you think it's not, quit here and try: sudo mount /dev/mmcblk0p1 /boot" + if ask "Continue?"; then + echo "Proceeding." + else + bail "Aborting." + fi +fi + +if [[ ! -e "$target_homedir" || ! -d "$target_homedir" ]]; then + bail "$target_homedir must be an existing directory (use -u /home/foo to specify)" +fi + +pitfttype=${PITFT_TYPES[$PITFT_SELECT-1]} +pitftrot=${PITFT_ROTATIONS[$PITFT_ROTATE-1]} + + +if [ "${pitfttype}" != "28r" ] && [ "${pitfttype}" != "28c" ] && [ "${pitfttype}" != "35r" ] && [ "${pitfttype}" != "22" ]; then + echo "Type must be one of:" + echo " '28r' (2.8\" resistive, PID 1601)" + echo " '28c' (2.8\" capacitive, PID 1983)" + echo " '35r' (3.5\" Resistive)" + echo " '22' (2.2\" no touch)" + echo + print_help +fi + +info PITFT "System update" +sysupdate || bail "Unable to apt-get update" + +info PITFT "Installing Python libraries & Software..." +softwareinstall || bail "Unable to install software" + +info PITFT "Updating /boot/config.txt..." +update_configtxt || bail "Unable to update /boot/config.txt" + +if [ "${pitfttype}" == "28r" ] || [ "${pitfttype}" == "35r" ] || [ "${pitfttype}" == "28c" ] ; then + info PITFT "Updating SysFS rules for Touchscreen..." + update_udev || bail "Unable to update /etc/udev/rules.d" + + info PITFT "Updating TSLib default calibration..." + update_pointercal || bail "Unable to update /etc/pointercal" +fi + +# ask for console access +if ask "Would you like the console to appear on the PiTFT display?"; then + info PITFT "Updating console to PiTFT..." + uninstall_fbcp || bail "Unable to uninstall fbcp" + install_console || bail "Unable to configure console" +else + info PITFT "Making sure console doesn't use PiTFT" + uninstall_console || bail "Unable to configure console" + + if ask "Would you like the HDMI display to mirror to the PiTFT display?"; then + info PITFT "Adding FBCP support..." + install_fbcp || bail "Unable to configure fbcp" + + if [ -e /etc/lightdm ]; then + info PITFT "Updating X11 default calibration..." + update_xorg || bail "Unable to update calibration" + fi + fi +fi + + +#info PITFT "Updating X11 setup tweaks..." +#update_x11profile || bail "Unable to update X11 setup" + +#if [ "${pitfttype}" != "35r" ]; then +# # ask for 'on/off' button +# if ask "Would you like GPIO #23 to act as a on/off button?"; then +# info PITFT "Adding GPIO #23 on/off to PiTFT..." +# install_onoffbutton || bail "Unable to add on/off button" +# fi +#fi + +# update_bootprefs || bail "Unable to set boot preferences" + + +info PITFT "Success!" +echo +echo "Settings take effect on next boot." +echo +echo -n "REBOOT NOW? [y/N] " +read +if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then + echo "Exiting without reboot." + exit 0 +fi +echo "Reboot started..." +reboot +exit 0