Skip to content

Instantly share code, notes, and snippets.

@chardane

chardane/boot.py Secret

Last active April 30, 2024 04:46
Show Gist options
  • Save chardane/a45bdff904bad04b124c9f41118997c8 to your computer and use it in GitHub Desktop.
Save chardane/a45bdff904bad04b124c9f41118997c8 to your computer and use it in GitHub Desktop.
Magic Shutdown Button for Raspberry Pi
# This will run before code.py!
#
# Code is derived from this Adafruit tutorial:
#
# Customizing USB Devices in Circuitpython:
# https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/circuitpy-midi-serial
import storage
import board, digitalio
from digitalio import DigitalInOut, Pull
import neopixel
button = DigitalInOut(board.SWITCH)
button.switch_to_input(pull=Pull.DOWN)
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1)
pixel.fill(0x0)
# Disable devices only if button is not pressed.
if not button.value:
pixel.fill((255, 255, 0))
storage.disable_usb_drive()
# Magic Shutdown Button for Raspberry Pi!
# Code is written for the Neokey Trinkey:
# https://www.adafruit.com/product/5020
#
# And is derived from these Adafruit tutorials:
#
# Neokey Trinkey:
# https://learn.adafruit.com/adafruit-neokey-trinkey/hid-and-cap-touch-example
import time
import board
import neopixel
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode # pylint: disable=unused-import
from digitalio import DigitalInOut, Pull
import touchio
# create the pixel and turn it off
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1)
pixel.fill(0x0)
time.sleep(1) # Sleep for a bit to avoid a race condition on some systems
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :)
# create the switch, add a pullup, start it with not being pressed
button = DigitalInOut(board.SWITCH)
button.switch_to_input(pull=Pull.DOWN)
button_state = False
# create the captouch element and start it with not touched
touch = touchio.TouchIn(board.TOUCH)
touch_state = False
# open the terminal, wait 1 sec, and type the shutdown command
key_output = (
{'keys': (Keycode.CONTROL, Keycode.ALT, Keycode.T), 'delay': 1},
{'keys': 'sudo shutdown -h now\n', 'delay': 0.1},
)
# our helper function will press the keys themselves
def make_keystrokes(keys, delay):
if isinstance(keys, str): # If it's a string...
keyboard_layout.write(keys) # ...Print the string
elif isinstance(keys, int): # If its a single key
keyboard.press(keys) # "Press"...
keyboard.release_all() # ..."Release"!
elif isinstance(keys, (list, tuple)): # If its multiple keys
keyboard.press(*keys) # "Press"...
keyboard.release_all() # ..."Release"!
time.sleep(delay)
while True:
if button.value and not button_state:
pixel.fill((255, 0, 255))
print("Button pressed.")
button_state = True
if not button.value and button_state:
pixel.fill(0x0)
print("Button released.")
if isinstance(key_output, (list, tuple)) and isinstance(key_output[0], dict):
for k in key_output:
make_keystrokes(k['keys'], k['delay'])
else:
make_keystrokes(key_output, delay=0)
button_state = False
if touch.value and not touch_state:
print("Touched!")
pixel.fill((0, 255, 0))
touch_state = True
if not touch.value and touch_state:
print("Untouched!")
pixel.fill(0x0)
touch_state = False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment