From anonymous, 1 Month ago, written in Python.
Embed
  1. import time
  2. import board
  3. import analogio
  4. import rotaryio
  5. import digitalio
  6. import usb_hid
  7. import adafruit_hid.mouse
  8.  
  9.  
  10. class Encoder:
  11.  
  12.     MULT = 2
  13.  
  14.     def __init__(self):
  15.         self.button = digitalio.DigitalInOut(board.GP7)
  16.         self.button.pull = digitalio.Pull.UP
  17.  
  18.         self.encoder = rotaryio.IncrementalEncoder(board.GP6, board.GP5)
  19.         self._last_pos = self.encoder.position
  20.  
  21.     def delta(self):
  22.         pos = self.encoder.position
  23.         d = self._last_pos - pos
  24.         self._last_pos = pos
  25.         return d * self.MULT
  26.  
  27.     @property
  28.     def clicked(self):
  29.         return not self.button.value
  30.  
  31.  
  32. class Joystick:
  33.  
  34.     # FIXME add a calibration mode saving those values
  35.  
  36.     HOR_LEFT = 51500
  37.     HOR_RIGHT = 12500
  38.     HOR_MID = 31400
  39.  
  40.     VERT_UP = 51000
  41.     VERT_DOWN = 15000
  42.     VERT_MID = 31600
  43.  
  44.     DEADZONE = 700
  45.  
  46.     MAX_SPEED = 15
  47.     DEFAULT_SPEED = 2
  48.     SPEED_INC_DELAY_MS = 50
  49.  
  50.     CLICK_DELAY_MS = 100
  51.  
  52.     def __init__(self):
  53.         self.button = digitalio.DigitalInOut(board.A2)
  54.         self.button.pull = digitalio.Pull.UP
  55.  
  56.         self.horizontal = analogio.AnalogIn(board.A0)
  57.         self.vertical = analogio.AnalogIn(board.A1)
  58.  
  59.         self.speed = self.DEFAULT_SPEED
  60.         self._speed_time = time.monotonic_ns()
  61.         self._click_time = 0
  62.  
  63.         #self.calibrate()
  64.  
  65.     def calibrate(self):
  66.         hor_sum = 0
  67.         vert_sum = 0
  68.  
  69.         hor_min = self.horizontal.value
  70.         vert_min = self.vertical.value
  71.         hor_max = self.horizontal.value
  72.         vert_max = self.vertical.value
  73.  
  74.         count = 50000
  75.         for i in range(count):
  76.             hor_sum += self.horizontal.value
  77.             hor_min = min(hor_min, self.horizontal.value)
  78.             hor_max = max(hor_max, self.horizontal.value)
  79.  
  80.             vert_sum += self.vertical.value
  81.             vert_min = min(vert_min, self.vertical.value)
  82.             vert_max = max(vert_max, self.vertical.value)
  83.  
  84.             #time.sleep(0.2)
  85.  
  86.         hor_avg = hor_sum / count
  87.         vert_avg = vert_sum / count
  88.  
  89.         print(f'vert: min {vert_min} max {vert_max} avg {vert_avg}')
  90.         print(f'hor: min {hor_min} max {hor_max} avg {hor_avg}')
  91.         return hor_avg, vert_avg
  92.  
  93.     def map_number(self, x, in_min, in_max, out_min, out_max):
  94.         # based on
  95.         assert in_min < in_max
  96.         assert out_min < out_max
  97.         #assert x >= in_min
  98.         #assert x <= in_max
  99.         return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
  100.  
  101.     def _adjust_speed(self, used):
  102.         now = time.monotonic_ns()
  103.         if now - self._speed_time < self.SPEED_INC_DELAY_MS * 1000000:
  104.             return
  105.  
  106.         self._speed_time = now
  107.  
  108.         if used and self.speed < self.MAX_SPEED:
  109.             self.speed += 1
  110.         elif not used:
  111.             self.speed = self.DEFAULT_SPEED
  112.         print(self.speed)
  113.  
  114.  
  115.     def read_values(self):
  116.         now = time.monotonic_ns()
  117.  
  118.         if self.clicked:
  119.             self._click_time = now
  120.         if now - self._click_time < _DELAY_MS * 1000000:
  121.             # FIXME handle drag
  122.             print("Click ignore")
  123.             return 0, 0
  124.  
  125.         hor_value = self.horizontal.value
  126.         vert_value = self.vertical.value
  127.  
  128.         if self.HOR_MID - self.DEADZONE < hor_value < self.HOR_MID + self.DEADZONE:
  129.             hor = 0
  130.         else:
  131.             hor = self.map_number(
  132.                 hor_value,
  133.                 self.HOR_RIGHT,
  134.                 self.HOR_LEFT,
  135.                 -self.speed,
  136.                 self.speed,
  137.             )
  138.  
  139.         if self.VERT_MID - self.DEADZONE < vert_value < self.VERT_MID + self.DEADZONE:
  140.             vert = 0
  141.         else:
  142.             vert = self.map_number(
  143.                 vert_value,
  144.                 self.VERT_DOWN,
  145.                 self.VERT_UP,
  146.                 -self.speed,
  147.                 self.speed,
  148.             )
  149.  
  150.         self._adjust_speed(hor != 0 or vert != 0)
  151.         print(f"h {hor_value} -> {hor}; v {vert_value} -> {vert}; s {self.speed}")
  152.         return -hor, -vert
  153.  
  154.     @property
  155.     def clicked(self):
  156.         return not self.button.value
  157.  
  158.  
  159. class Led:
  160.  
  161.     def __init__(self):
  162.         self.r = digitalio.DigitalInOut(board.LED_R)
  163.         self.r.direction = digitalio.Direction.OUTPUT
  164.         self.r.value = True
  165.  
  166.         self.g = digitalio.DigitalInOut(board.LED_G)
  167.         self.g.direction = digitalio.Direction.OUTPUT
  168.         self.g.value = True
  169.  
  170.         self.b = digitalio.DigitalInOut(board.LED_B)
  171.         self.b.direction = digitalio.Direction.OUTPUT
  172.         self.b.value = True
  173.  
  174.     def set_r(self, value):
  175.         self.r.value = not value
  176.  
  177.     def set_g(self, value):
  178.         self.g.value = not value
  179.  
  180.     def set_b(self, value):
  181.         self.b.value = not value
  182.  
  183.  
  184. mouse = adafruit_hid.mouse.Mouse(usb_hid.devices)
  185. enc = Encoder()
  186. joy = Joystick()
  187. led = Led()
  188.  
  189. while True:
  190.     hor, vert = _values()
  191.     wheel = ()
  192.  
  193.     mouse.move(x=hor, y=vert, wheel=wheel)
  194.  
  195.     #print(hor, vert, wheel)
  196.  
  197.     led.set_r(enc.clicked)
  198.     led.set_g(joy.clicked)
  199.  
  200.     if enc.clicked:
  201.         (adafruit_hid.mouse.Mouse.LEFT_BUTTON)
  202.     elif joy.clicked:
  203.         (adafruit_hid.mouse.Mouse.LEFT_BUTTON)
  204.