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 digitalio
  8  import simpleio
  9  import adafruit_lsm6ds.lsm6ds33
 10  import adafruit_apds9960.apds9960
 11  from adafruit_hid.mouse import Mouse
 12  
 13  import adafruit_ble
 14  from adafruit_ble.advertising import Advertisement
 15  from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
 16  from adafruit_ble.services.standard.hid import HIDService
 17  from adafruit_ble.services.standard.device_info import DeviceInfoService
 18  
 19  #  setup I2C
 20  i2c = board.I2C()
 21  
 22  #  setup accelerometer
 23  lsm6ds33 = adafruit_lsm6ds.lsm6ds33.LSM6DS33(i2c)
 24  #  setup proximity sensor
 25  apds9960 = adafruit_apds9960.apds9960.APDS9960(i2c)
 26  
 27  #  enable proximity sensor
 28  apds9960.enable_proximity = True
 29  
 30  #  setup for onboard button
 31  click = digitalio.DigitalInOut(board.SWITCH)
 32  click.direction = digitalio.Direction.INPUT
 33  click.pull = digitalio.Pull.UP
 34  
 35  #  rounding algorhythm used for mouse movement
 36  #  as used in the HID mouse CircuitPython example
 37  mouse_min = -9
 38  mouse_max = 9
 39  step = (mouse_max - mouse_min) / 20.0
 40  
 41  def steps(axis):
 42      return round((axis - mouse_min) / step)
 43  
 44  #  time.monotonic() variable
 45  clock = 0
 46  
 47  #  variable for distance for proximity scrolling
 48  distance = 245
 49  
 50  #  setup for HID and BLE
 51  hid = HIDService()
 52  
 53  device_info = DeviceInfoService(software_revision=adafruit_ble.__version__,
 54                                  manufacturer="Adafruit Industries")
 55  advertisement = ProvideServicesAdvertisement(hid)
 56  advertisement.appearance = 961
 57  scan_response = Advertisement()
 58  scan_response.complete_name = "CircuitPython HID"
 59  
 60  ble = adafruit_ble.BLERadio()
 61  
 62  if not ble.connected:
 63      print("advertising")
 64      ble.start_advertising(advertisement, scan_response)
 65  else:
 66      print("already connected")
 67      print(ble.connections)
 68  
 69  #  setup for mouse
 70  mouse = Mouse(hid.devices)
 71  
 72  while True:
 73      while not ble.connected:
 74          pass
 75      while ble.connected:
 76          #  sets x and y values for accelerometer x and y values
 77          #  x and y are swapped for orientation of feather
 78          y, x, z = lsm6ds33.acceleration
 79  
 80          #  map range of horizontal movement to mouse x movement
 81          horizontal_mov = simpleio.map_range(steps(x), 1.0, 20.0, -15.0, 15.0)
 82          #  map range of vertical movement to mouse y movement
 83          vertical_mov = simpleio.map_range(steps(y), 20.0, 1.0, -15.0, 15.0)
 84          #  map range of mouse y movement to scrolling
 85          scroll_dir = simpleio.map_range(vertical_mov, -15.0, 15.0, 3.0, -3.0)
 86  
 87          #  if onboard button is pressed, sends left mouse click
 88          if not click.value:
 89              mouse.click(Mouse.LEFT_BUTTON)
 90              time.sleep(0.2)
 91          #  if the proximity sensor is covered
 92          #  scroll the mouse
 93          if apds9960.proximity > distance:
 94              mouse.move(wheel=int(scroll_dir))
 95          #  otherwise move mouse cursor in x and y directions
 96          else:
 97              mouse.move(x=int(horizontal_mov))
 98              mouse.move(y=int(vertical_mov))
 99  
100          #  debugging print for x and y values
101          #  time.monotonic() is used so that the
102          #  code is not delayed with time.sleep
103          if (clock + 2) < time.monotonic():
104              print("x", steps(x))
105              print("y", steps(y))
106              clock = time.monotonic()
107  
108      ble.start_advertising(advertisement)