Add code for mouse support in NeXT keyboard
This commit is contained in:
parent
f6a77d233d
commit
b5807737bd
1 changed files with 63 additions and 4 deletions
|
|
@ -10,6 +10,7 @@ from keypad import Keys
|
|||
from adafruit_hid.consumer_control import ConsumerControl
|
||||
from adafruit_hid.keyboard import Keyboard
|
||||
from adafruit_hid.keyboard import Keycode
|
||||
from adafruit_hid.mouse import Mouse
|
||||
from adafruit_pioasm import Program
|
||||
from adafruit_ticks import ticks_add, ticks_less, ticks_ms
|
||||
from next_keycode import (
|
||||
|
|
@ -21,6 +22,14 @@ from next_keycode import (
|
|||
shift_modifiers,
|
||||
)
|
||||
|
||||
|
||||
# Compared to a modern mouse, the DPI of the NeXT mouse is low. Increasing this
|
||||
# number makes the pointer move further faster, but it also makes moves chunky.
|
||||
# Customize this number according to the trade-off you want, but also check
|
||||
# whether your operating system can assign a higher "sensitivity" or
|
||||
# "acceleration" for the mouse.
|
||||
MOUSE_SCALE = 8
|
||||
|
||||
# Customize the power key's keycode. You can change it to `Keycode.POWER` if
|
||||
# you really want to accidentally power off your computer!
|
||||
POWER_KEY_SENDS = Keycode.F1
|
||||
|
|
@ -79,7 +88,8 @@ def set_leds(i):
|
|||
return pack_message_str(f"0000000001110{i:02b}0000000")
|
||||
|
||||
|
||||
QUERY = pack_message_str("000001000", 1)
|
||||
QUERY = pack_message_str("000001000", True)
|
||||
MOUSEQUERY = pack_message_str("010001000", True)
|
||||
RESET = pack_message_str("0111101111110000000000")
|
||||
|
||||
BIT_BREAK = 1 << 11
|
||||
|
|
@ -94,12 +104,19 @@ def is_mod_report(report):
|
|||
return not bool(report & BIT_MOD)
|
||||
|
||||
|
||||
def extract_bits(report, *positions):
|
||||
result = 0
|
||||
for p in positions:
|
||||
result = (result << 1)
|
||||
if report & (1 << p):
|
||||
result |= 1
|
||||
#result = (result << 1) | bool(report & (1<<p))
|
||||
return result
|
||||
|
||||
# keycode bits are backwards compared to other information sources
|
||||
# (bit 0 is first)
|
||||
def keycode(report):
|
||||
b = f"{report >> 12:07b}"
|
||||
b = "".join(reversed(b))
|
||||
return int(b, 2)
|
||||
return extract_bits(report, 12, 13, 14, 15, 16, 17, 18)
|
||||
|
||||
|
||||
def modifiers(report):
|
||||
|
|
@ -122,11 +139,18 @@ sm = rp2pio.StateMachine(
|
|||
)
|
||||
|
||||
|
||||
def signfix(num, sign_pos):
|
||||
"""Fix a signed number if the bit with weight `sign_pos` is actually the sign bit"""
|
||||
if num & sign_pos:
|
||||
return num - 2*sign_pos
|
||||
return num
|
||||
|
||||
class KeyboardHandler:
|
||||
def __init__(self):
|
||||
self.old_modifiers = 0
|
||||
self.cc = ConsumerControl(usb_hid.devices)
|
||||
self.kbd = Keyboard(usb_hid.devices)
|
||||
self.mouse = Mouse(usb_hid.devices)
|
||||
|
||||
def set_key_state(self, key, state):
|
||||
if state:
|
||||
|
|
@ -144,6 +168,27 @@ class KeyboardHandler:
|
|||
else:
|
||||
self.kbd.release(key)
|
||||
|
||||
def handle_mouse_report(self, report):
|
||||
if report == 1536: # the "nothing happened" report
|
||||
return
|
||||
|
||||
dx = extract_bits(report, 11,12,13,14,15,16,17)
|
||||
dx = -signfix(dx, 64)
|
||||
dy = extract_bits(report, 0,1,2,3,4,5,6)
|
||||
dy = -signfix(dy, 64)
|
||||
b1 = not extract_bits(report, 18)
|
||||
b2 = not extract_bits(report, 7)
|
||||
|
||||
self.mouse.report[0] = (
|
||||
Mouse.MIDDLE_BUTTON if (b1 and b2) else
|
||||
Mouse.LEFT_BUTTON if b1 else
|
||||
Mouse.RIGHT_BUTTON if b2
|
||||
else 0)
|
||||
if dx or dy:
|
||||
self.mouse.move(dx * MOUSE_SCALE, dy * MOUSE_SCALE)
|
||||
else:
|
||||
self.mouse._send_no_move() # pylint: disable=protected-access
|
||||
|
||||
def handle_report(self, report_value):
|
||||
if report_value == 1536: # the "nothing happened" report
|
||||
return
|
||||
|
|
@ -205,5 +250,19 @@ try:
|
|||
sm.restart()
|
||||
sm.write(RESET)
|
||||
time.sleep(0.1)
|
||||
|
||||
sm.write(MOUSEQUERY)
|
||||
deadline = ticks_add(ticks_ms(), 100)
|
||||
while ticks_less(ticks_ms(), deadline):
|
||||
if sm.in_waiting:
|
||||
sm.readinto(recv_buf)
|
||||
value = recv_buf[0]
|
||||
handler.handle_mouse_report(value)
|
||||
break
|
||||
else:
|
||||
print("keyboard did not respond - resetting")
|
||||
sm.restart()
|
||||
sm.write(RESET)
|
||||
time.sleep(0.1)
|
||||
finally: # Release all keys before e.g., code is reloaded
|
||||
handler.kbd.release_all()
|
||||
|
|
|
|||
Loading…
Reference in a new issue