code.py
  1  # SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  import ipaddress
  6  import wifi
  7  import socketpool
  8  import board
  9  import simpleio
 10  import adafruit_tsc2007
 11  import adafruit_adxl34x
 12  
 13  # Get wifi details and host IP from a secrets.py file
 14  try:
 15      from secrets import secrets
 16  except ImportError:
 17      print("WiFi secrets are kept in secrets.py, please add them there!")
 18      raise
 19  
 20  #  I2C setup for STEMMA port
 21  i2c = board.STEMMA_I2C()
 22  
 23  #  touchscreen setup for TSC2007
 24  irq_dio = None
 25  tsc = adafruit_tsc2007.TSC2007(i2c, irq=irq_dio)
 26  
 27  #  accelerometer setup
 28  accelerometer = adafruit_adxl34x.ADXL343(i2c)
 29  accelerometer.enable_tap_detection()
 30  
 31  #  MIDI notes - 2 octaves of Cmaj7 triad
 32  notes = [48, 52, 55, 59, 60, 64, 67, 71]
 33  #  reads touch input
 34  point = tsc.touch
 35  #  accelerometer x coordinate
 36  acc_x = 0
 37  #  accelerometer y coordinate
 38  acc_y = 0
 39  #  last accelerometer x coordinate
 40  last_accX = 0
 41  #  last accelerometer y coordinate
 42  last_accY = 0
 43  #  mapped value for touchscreen x coordinate
 44  x_map = 0
 45  #  mapped value for touchscreen y coordinate
 46  y_map = 0
 47  #  last mapped value for touchscreen x coordinate
 48  last_x = 0
 49  #  last mapped value for touchscreen y coordinate
 50  last_y = 0
 51  #  state for whether synth is running
 52  run = 0
 53  #  tap detection state
 54  last_tap = False
 55  #  new value detection state
 56  new_val = False
 57  
 58  # URLs to fetch from
 59  HOST = secrets["host"]
 60  PORT = 12345
 61  TIMEOUT = 5
 62  INTERVAL = 5
 63  MAXBUF = 256
 64  
 65  #  connect to WIFI
 66  print("Connecting to %s"%secrets["ssid"])
 67  wifi.radio.connect(secrets["ssid"], secrets["password"])
 68  print("Connected to %s!"%secrets["ssid"])
 69  
 70  pool = socketpool.SocketPool(wifi.radio)
 71  
 72  ipv4 = ipaddress.ip_address(pool.getaddrinfo(HOST, PORT)[0][4][0])
 73  
 74  buf = bytearray(MAXBUF)
 75  
 76  print("Create TCP Client Socket")
 77  s = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
 78  
 79  print("Connecting")
 80  s.connect((HOST, PORT))
 81  
 82  while True:
 83      #  tap detection
 84      #  if tap is detected and the synth is not running...
 85      if accelerometer.events["tap"] and not last_tap and not run:
 86          #  run is updated to 1
 87          run = 1
 88          #  last_tap is reset
 89          last_tap = True
 90          print("running")
 91          #  message is sent to Pd to start the synth
 92          #  all Pd messages need to end with a ";"
 93          size = s.send(str.encode(' '.join(["run", str(run), ";"])))
 94      #  if tap is detected and the synth is running...
 95      if accelerometer.events["tap"] and not last_tap and run:
 96          #  run is updated to 0
 97          run = 0
 98          #  last_tap is reset
 99          last_tap = True
100          print("not running")
101          #  message is sent to Pd to stop the synth
102          #  all Pd messages need to end with a ";"
103          size = s.send(str.encode(' '.join(["run", str(run), ";"])))
104      #  tap detection debounce
105      if not accelerometer.events["tap"] and last_tap:
106          last_tap = False
107  
108      #  if the touchscreen is touched...
109      if tsc.touched:
110          #  point holds touch data
111          point = tsc.touch
112          #  x coordinate is remapped to 0 - 8
113          x_map = simpleio.map_range(point["x"], 0, 4095, 0, 8)
114          #  y coordinate is remapped to 0 - 8
115          y_map = simpleio.map_range(point["y"], 0, 4095, 0, 8)
116  
117      #  accelerometer x value is remapped for synth filter
118      acc_x = simpleio.map_range(accelerometer.acceleration[0], -10, 10, 450, 1200)
119      #  accelerometer y value is remapped for synth filter
120      acc_y = simpleio.map_range(accelerometer.acceleration[1], -10, 10, 250, 750)
121  
122      #  if any of the values are different from the last value...
123      if x_map != last_x:
124          #  last value is updated
125          last_x = x_map
126          #  new value is detected
127          new_val = True
128      if y_map != last_y:
129          last_y = y_map
130          new_val = True
131      if int(acc_x) != last_accX:
132          last_accX = int(acc_x)
133          new_val = True
134      if int(acc_y) != last_accY:
135          last_accY = int(acc_y)
136          new_val = True
137  
138      #  if a new value is detected...
139      if new_val:
140          #  note index is updated to y coordinate on touch screen
141          note = notes[int(y_map)]
142          #  message with updated values is sent via socket to Pd
143          #  all Pd messages need to end with a ";"
144          size = s.send(str.encode(' '.join(["x", str(x_map), ";",
145                                             "y", str(y_map), ";",
146                                             "aX", str(acc_x), ";",
147                                             "aY", str(acc_y), ";",
148                                             "n", str(note), ";"])))
149          #  new_val is reset
150          new_val = False