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.

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