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.

279 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-imaging"
  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. apt-get install -y --force-yes python-pip python-dev python-imaging python-smbus
  130. pip install numpy pi3d svg.path adafruit-ads1x15
  131. # smbus and ads1x15 Python libs are installed regardless whether ADC
  132. # is enabled; simplifies the Python code a little (no "uncomment this")
  133. echo "Installing Adafruit code and data in /boot..."
  134. cd /tmp
  135. curl -LO https://github.com/adafruit/Pi_Eyes/archive/master.zip
  136. unzip master.zip
  137. # Moving between filesystems requires copy-and-delete:
  138. cp -r Pi_Eyes-master /boot/Pi_Eyes
  139. rm -rf master.zip Pi_Eyes-master
  140. if [ $INSTALL_HALT -ne 0 ]; then
  141. echo "Installing gpio-halt in /usr/local/bin..."
  142. curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
  143. unzip master.zip
  144. cd Adafruit-GPIO-Halt-master
  145. make
  146. mv gpio-halt /usr/local/bin
  147. cd ..
  148. rm -rf Adafruit-GPIO-Halt-master
  149. fi
  150. # CONFIG -------------------------------------------------------------------
  151. echo "Configuring system..."
  152. # Disable overscan compensation (use full screen):
  153. raspi-config nonint do_overscan 1
  154. # HDMI settings for Pi eyes
  155. reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
  156. reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
  157. reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
  158. if [ $SCREEN_SELECT -eq 3 ]; then
  159. # IPS display - set HDMI to 1280x720
  160. reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
  161. else
  162. # All others - set HDMI to 640x480
  163. reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
  164. fi
  165. # Enable I2C for ADC
  166. if [ $INSTALL_ADC -ne 0 ]; then
  167. raspi-config nonint do_i2c 0
  168. fi
  169. if [ $INSTALL_HALT -ne 0 ]; then
  170. # Add gpio-halt to /rc.local:
  171. grep gpio-halt /etc/rc.local >/dev/null
  172. if [ $? -eq 0 ]; then
  173. # gpio-halt already in rc.local, but make sure correct:
  174. sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
  175. else
  176. # Insert gpio-halt into rc.local before final 'exit 0'
  177. sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
  178. fi
  179. fi
  180. # If using OLED, TFT or IPS, enable SPI and install fbx2 and eyes.py,
  181. # else (HDMI) skip SPI, fbx2 and install cyclops.py (single eye)
  182. if [ $SCREEN_SELECT -ne 4 ]; then
  183. # Enable SPI0 using raspi-config
  184. raspi-config nonint do_spi 0
  185. # Enable SPI1 by adding overlay to /boot/config.txt
  186. reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
  187. reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
  188. # Adjust spidev buffer size to 8K (default is 4K)
  189. reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
  190. SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
  191. # Auto-start fbx2 on boot
  192. grep fbx2 /etc/rc.local >/dev/null
  193. if [ $? -eq 0 ]; then
  194. # fbx2 already in rc.local, but make sure correct:
  195. sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
  196. else
  197. # Insert fbx2 into rc.local before final 'exit 0'
  198. sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
  199. fi
  200. RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
  201. # Auto-start eyes.py on boot
  202. grep eyes.py /etc/rc.local >/dev/null
  203. if [ $? -eq 0 ]; then
  204. # eyes.py already in rc.local, but make sure correct:
  205. sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
  206. else
  207. # Insert eyes.py into rc.local before final 'exit 0'
  208. sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
  209. fi
  210. else
  211. # Auto-start cyclops.py on boot
  212. grep cyclops.py /etc/rc.local >/dev/null
  213. if [ $? -eq 0 ]; then
  214. # cyclops.py already in rc.local, but make sure correct:
  215. sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python cyclops.py \&/g" /etc/rc.local >/dev/null
  216. else
  217. # Insert cyclops.py into rc.local before final 'exit 0'
  218. sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
  219. fi
  220. fi
  221. if [ $INSTALL_GADGET -ne 0 ]; then
  222. reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
  223. grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
  224. if [ $? -ne 0 ]; then
  225. # Insert ethernet gadget into config.txt after 'rootwait'
  226. sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
  227. fi
  228. fi
  229. # PROMPT FOR REBOOT --------------------------------------------------------
  230. echo "Done."
  231. echo
  232. echo "Settings take effect on next boot."
  233. echo
  234. echo -n "REBOOT NOW? [y/N] "
  235. read
  236. if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
  237. echo "Exiting without reboot."
  238. exit 0
  239. fi
  240. echo "Reboot started..."
  241. reboot
  242. exit 0