You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
8.3 KiB

  1. #!/bin/bash
  2. if [ $(id -u) -ne 0 ]; then
  3. echo "Installer must be run as root."
  4. echo "Try 'sudo bash $0'"
  5. exit 1
  6. fi
  7. clear
  8. # smbus and ads1x15 Python libs are installed regardless whether ADC
  9. echo "This script installs software for the Adafruit"
  10. echo "Snake Eyes Bonnet for Raspberry Pi. Steps include:"
  11. echo "- Update package index files (apt-get update)"
  12. echo "- Install Python libraries: numpy, pi3d, svg.path,"
  13. echo " rpi-gpio, python3-dev, python3-pil"
  14. echo "- Install Adafruit eye code and data in /boot"
  15. echo "- Enable SPI0 and SPI1 peripherals if needed"
  16. echo "- Set HDMI resolution, disable overscan"
  17. echo "Run time ~25 minutes. Reboot required."
  18. echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
  19. echo
  20. echo -n "CONTINUE? [y/N] "
  21. read
  22. if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
  23. echo "Canceled."
  24. exit 0
  25. fi
  26. # FEATURE PROMPTS ----------------------------------------------------------
  27. # Installation doesn't begin until after all user input is taken.
  28. INSTALL_HALT=0
  29. INSTALL_ADC=0
  30. INSTALL_GADGET=0
  31. # Given a list of strings representing options, display each option
  32. # preceded by a number (1 to N), display a prompt, check input until
  33. # a valid number within the selection range is entered.
  34. selectN() {
  35. for ((i=1; i<=$#; i++)); do
  36. echo $i. ${!i}
  37. done
  38. echo
  39. REPLY=""
  40. while :
  41. do
  42. echo -n "SELECT 1-$#: "
  43. read
  44. if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
  45. return $REPLY
  46. fi
  47. done
  48. }
  49. SCREEN_VALUES=(-o -t -i)
  50. SCREEN_NAMES=("OLED (128x128)" "TFT (128x128)" "IPS (240x240)" HDMI)
  51. RADIUS_VALUES=(128 128 240)
  52. OPTION_NAMES=(NO YES)
  53. echo
  54. echo "Select screen type:"
  55. selectN "${SCREEN_NAMES[0]}" \
  56. "${SCREEN_NAMES[1]}" \
  57. "${SCREEN_NAMES[2]}" \
  58. "${SCREEN_NAMES[3]}"
  59. SCREEN_SELECT=$?
  60. echo -n "Install GPIO-halt utility? [y/N] "
  61. read
  62. if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
  63. INSTALL_HALT=1
  64. echo -n "GPIO pin for halt: "
  65. read
  66. HALT_PIN=$REPLY
  67. fi
  68. echo -n "Install ADC support? [y/N] "
  69. read
  70. if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
  71. INSTALL_ADC=1
  72. fi
  73. echo -n "Install USB Ethernet gadget support? (Pi Zero) [y/N] "
  74. read
  75. if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
  76. INSTALL_GADGET=1
  77. fi
  78. echo
  79. echo "Screen type: ${SCREEN_NAMES[$SCREEN_SELECT-1]}"
  80. if [ $INSTALL_HALT -eq 1 ]; then
  81. echo "Install GPIO-halt: YES (GPIO$HALT_PIN)"
  82. else
  83. echo "Install GPIO-halt: NO"
  84. fi
  85. echo "ADC support: ${OPTION_NAMES[$INSTALL_ADC]}"
  86. echo "Ethernet USB gadget support: ${OPTION_NAMES[$INSTALL_GADGET]}"
  87. if [ $SCREEN_SELECT -eq 3 ]; then
  88. echo "Video resolution will be set to 1280x720, no overscan"
  89. else
  90. echo "Video resolution will be set to 640x480, no overscan"
  91. fi
  92. echo
  93. echo -n "CONTINUE? [y/N] "
  94. read
  95. if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
  96. echo "Canceled."
  97. exit 0
  98. fi
  99. # START INSTALL ------------------------------------------------------------
  100. # All selections are validated at this point...
  101. # Given a filename, a regex pattern to match and a replacement string,
  102. # perform replacement if found, else append replacement to end of file.
  103. # (# $1 = filename, $2 = pattern to match, $3 = replacement)
  104. reconfig() {
  105. grep $2 $1 >/dev/null
  106. if [ $? -eq 0 ]; then
  107. # Pattern found; replace in file
  108. sed -i "s/$2/$3/g" $1 >/dev/null
  109. else
  110. # Not found; append (silently)
  111. echo $3 | sudo tee -a $1 >/dev/null
  112. fi
  113. }
  114. # Same as above, but appends to same line rather than new line
  115. reconfig2() {
  116. grep $2 $1 >/dev/null
  117. if [ $? -eq 0 ]; then
  118. # Pattern found; replace in file
  119. sed -i "s/$2/$3/g" $1 >/dev/null
  120. else
  121. # Not found; append to line (silently)
  122. sed -i "s/$/ $3/g" $1 >/dev/null
  123. fi
  124. }
  125. echo
  126. echo "Starting installation..."
  127. echo "Updating package index files..."
  128. apt-get update
  129. echo "Installing Python libraries..."
  130. # WAS: apt-get install -y --force-yes python-pip python-dev python-imaging python-smbus
  131. apt-get install -y python3-pip python3-dev python3-pil python3-smbus libatlas-base-dev
  132. # WAS: pip3 install numpy pi3d svg.path rpi-gpio adafruit-ads1x15
  133. pip3 install numpy pi3d==2.34 svg.path rpi-gpio adafruit-blinka adafruit-circuitpython-ads1x15
  134. # smbus and Blinka+ADC libs are installed regardless whether ADC is
  135. # enabled; simplifies the Python code a little (no "uncomment this")
  136. echo "Installing Adafruit code and data in /boot..."
  137. cd /tmp
  138. curl -LO https://github.com/adafruit/Pi_Eyes/archive/master.zip
  139. unzip master.zip
  140. # Moving between filesystems requires copy-and-delete:
  141. cp -r Pi_Eyes-master /boot/Pi_Eyes
  142. rm -rf master.zip Pi_Eyes-master
  143. if [ $INSTALL_HALT -ne 0 ]; then
  144. echo "Installing gpio-halt in /usr/local/bin..."
  145. curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
  146. unzip master.zip
  147. cd Adafruit-GPIO-Halt-master
  148. make
  149. mv gpio-halt /usr/local/bin
  150. cd ..
  151. rm -rf Adafruit-GPIO-Halt-master
  152. fi
  153. # CONFIG -------------------------------------------------------------------
  154. echo "Configuring system..."
  155. # Disable overscan compensation (use full screen):
  156. raspi-config nonint do_overscan 1
  157. # HDMI settings for Pi eyes
  158. reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
  159. reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
  160. reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
  161. if [ $SCREEN_SELECT -eq 3 ]; then
  162. # IPS display - set HDMI to 1280x720
  163. reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
  164. else
  165. # All others - set HDMI to 640x480
  166. reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
  167. fi
  168. # Enable I2C for ADC
  169. if [ $INSTALL_ADC -ne 0 ]; then
  170. raspi-config nonint do_i2c 0
  171. fi
  172. if [ $INSTALL_HALT -ne 0 ]; then
  173. # Add gpio-halt to /rc.local:
  174. grep gpio-halt /etc/rc.local >/dev/null
  175. if [ $? -eq 0 ]; then
  176. # gpio-halt already in rc.local, but make sure correct:
  177. sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
  178. else
  179. # Insert gpio-halt into rc.local before final 'exit 0'
  180. sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
  181. fi
  182. fi
  183. # If using OLED, TFT or IPS, enable SPI and install fbx2 and eyes.py,
  184. # else (HDMI) skip SPI, fbx2 and install cyclops.py (single eye)
  185. if [ $SCREEN_SELECT -ne 4 ]; then
  186. # Enable SPI0 using raspi-config
  187. raspi-config nonint do_spi 0
  188. # Enable SPI1 by adding overlay to /boot/config.txt
  189. reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
  190. reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
  191. # Adjust spidev buffer size to 8K (default is 4K)
  192. reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
  193. SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
  194. # Auto-start fbx2 on boot
  195. grep fbx2 /etc/rc.local >/dev/null
  196. if [ $? -eq 0 ]; then
  197. # fbx2 already in rc.local, but make sure correct:
  198. sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
  199. else
  200. # Insert fbx2 into rc.local before final 'exit 0'
  201. sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
  202. fi
  203. RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
  204. # Auto-start eyes.py on boot
  205. grep eyes.py /etc/rc.local >/dev/null
  206. if [ $? -eq 0 ]; then
  207. # eyes.py already in rc.local, but make sure correct:
  208. sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
  209. else
  210. # Insert eyes.py into rc.local before final 'exit 0'
  211. sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
  212. fi
  213. else
  214. # Auto-start cyclops.py on boot
  215. grep cyclops.py /etc/rc.local >/dev/null
  216. if [ $? -eq 0 ]; then
  217. # cyclops.py already in rc.local, but make sure correct:
  218. sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python3 cyclops.py \&/g" /etc/rc.local >/dev/null
  219. else
  220. # Insert cyclops.py into rc.local before final 'exit 0'
  221. sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
  222. fi
  223. fi
  224. if [ $INSTALL_GADGET -ne 0 ]; then
  225. reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
  226. grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
  227. if [ $? -ne 0 ]; then
  228. # Insert ethernet gadget into config.txt after 'rootwait'
  229. sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
  230. fi
  231. fi
  232. # PROMPT FOR REBOOT --------------------------------------------------------
  233. echo "Done."
  234. echo
  235. echo "Settings take effect on next boot."
  236. echo
  237. echo -n "REBOOT NOW? [y/N] "
  238. read
  239. if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
  240. echo "Exiting without reboot."
  241. exit 0
  242. fi
  243. echo "Reboot started..."
  244. reboot
  245. exit 0