code.py
  1  # SPDX-FileCopyrightText: 2021 Liz Clark for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  import time
  6  import board
  7  import neopixel
  8  import touchio
  9  import usb_hid
 10  from rainbowio import colorwheel
 11  from adafruit_hid.keyboard import Keyboard
 12  from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
 13  from adafruit_hid.keycode import Keycode
 14  
 15  #  setup for onboard neopixels
 16  pixel_pin = board.NEOPIXEL
 17  num_pixels = 4
 18  
 19  pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.05, auto_write=False)
 20  
 21  #  setup for cap touch pads
 22  top_touch = touchio.TouchIn(board.TOUCH1)
 23  bot_touch = touchio.TouchIn(board.TOUCH2)
 24  
 25  #  HID keyboard input setup
 26  keyboard = Keyboard(usb_hid.devices)
 27  keyboard_layout = KeyboardLayoutUS(keyboard)
 28  #  variable for the ALT key
 29  alt_key = Keycode.ALT
 30  
 31  
 32  def rainbow_cycle(wait):
 33      for j in range(255):
 34          for i in range(num_pixels):
 35              rc_index = (i * 256 // num_pixels) + j
 36              pixels[i] = colorwheel(rc_index & 255)
 37          pixels.show()
 38          time.sleep(wait)
 39  
 40  #  variables for colors
 41  RED = (255, 0, 0)
 42  GREEN = (0, 255, 0)
 43  
 44  #  state machines
 45  #  cap touch debouncing
 46  bot_pressed = False
 47  top_pressed = False
 48  #  default mute states
 49  mic_mute = True
 50  vid_mute = True
 51  #  time.monotonic() tracker
 52  clock = time.monotonic()
 53  #  tracking for initiating an exit from the meeting
 54  escape = False
 55  escape_1 = False
 56  escape_2 = False
 57  
 58  while True:
 59      #  cap touch debouncing
 60      if not top_touch.value and top_pressed:
 61          top_pressed = False
 62      if not bot_touch.value and bot_pressed:
 63          bot_pressed = False
 64      #  if your mic is muted...
 65      if mic_mute:
 66          #  neopixels are red
 67          pixels[0] = RED
 68          pixels[1] = RED
 69          pixels.show()
 70      #  if your camera is muted...
 71      if vid_mute:
 72          #  neopixels are red
 73          pixels[2] = RED
 74          pixels[3] = RED
 75          pixels.show()
 76      #  if your mic is NOT muted...
 77      if not mic_mute:
 78          #  neopixels are green
 79          pixels[0] = GREEN
 80          pixels[1] = GREEN
 81          pixels.show()
 82      #  if your camera is NOT muted...
 83      if not vid_mute:
 84          #  neopixels are green
 85          pixels[2] = GREEN
 86          pixels[3] = GREEN
 87          pixels.show()
 88      #  if you are leaving the meeting...
 89      if escape:
 90          #  neopixels are rainbow
 91          rainbow_cycle(0)
 92          #  resets exit states
 93          escape = False
 94          escape_1 = False
 95          escape_2 = False
 96          mic_mute = True
 97          vid_mute = True
 98      #  if you press the top touch cap touch pad...
 99      if (top_touch.value and not top_pressed):
100          top_pressed = True
101          #  start time count for exit
102          clock = time.monotonic()
103          #  slight delay so that you don't automatically mute/unmute
104          #  if your intent is to exit
105          time.sleep(0.12)
106          #  if after the delay you're still pressing the cap touch pad...
107          if top_touch.value and top_pressed:
108              print("escape top")
109              #  initial escape state is set to true
110              escape_1 = True
111          #  if you aren't still pressing the cap touch pad...
112          else:
113              #  if your camera was muted...
114              if vid_mute:
115                  print("top")
116                  #  your camera is NOT muted
117                  vid_mute = False
118                  #  resets escape state just in case
119                  escape_1 = False
120              #  if your camera was NOT muted...
121              elif not vid_mute:
122                  print("top")
123                  #  your camera is muted
124                  vid_mute = True
125                  #  resets escape state just in case
126                  escape_1 = False
127              #  sends camera mute/unmute shortcut
128              keyboard.send(alt_key, Keycode.V)
129      #  if you press the top touch cap touch pad...
130      if (bot_touch.value and not bot_pressed):
131          bot_pressed = True
132          #  start time count for exit
133          clock = time.monotonic()
134          #  slight delay so that you don't automatically mute/unmute
135          #  if your intent is to exit
136          time.sleep(0.12)
137          #  if after the delay you're still pressing the cap touch pad...
138          if bot_touch.value and bot_pressed:
139              print("escape bot")
140              #  initial escape state is set to true
141              escape_2 = True
142          #  if you aren't still pressing the cap touch pad...
143          else:
144              #  if your mic was muted...
145              if mic_mute:
146                  print("bot")
147                  #  your mic is NOT muted
148                  mic_mute = False
149                  #  resets escape state just in case
150                  escape_2 = False
151              #  if your mic was NOT muted...
152              elif not mic_mute:
153                  print("bot")
154                  #  your mic is muted
155                  mic_mute = True
156                  #  resets escape state just in case
157                  escape_2 = False
158              #  sends mic mute/unmute shortcut
159              keyboard.send(alt_key, Keycode.A)
160      #  if you held down both cap touch pads and 2 seconds has passed...
161      if ((clock + 2) < time.monotonic()) and (escape_1 and escape_2):
162          print("escape")
163          #  full escape state is set
164          escape = True
165          #  sends exit meeting shortcut
166          keyboard.send(alt_key, Keycode.Q)
167          #  brief delay for confirmation window to open
168          time.sleep(0.1)
169          #  sends enter to confirm meeting exit
170          keyboard.send(Keycode.ENTER)