because i can.
A replica from my tweet from a while ago.
because i can.
Video 1: A morse key connected to an Adafruit Feather RP2040, running home-brewn CircuitPython code whcih interprets morse input and emulates a USB HID keyboard, sending characters to the Twitter app on Android.
Original source: because i can.
The code is a simple Gist on Github, but below you can see the full code for reference. It needs some serious improvements, but it’s good enough for me.
To be really useful as a keyboard, the set of morse codepoints was extended; instead of doing it myself, I borrowed the existing set from Google’s GBoard morse implementation, as described by Nathan Vander Wilt.
import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
lookup = { ".-":"a", "-...":"b", "-.-.":"c", "-..":"d", ".":"e", "..-.":"f",
"--.":"g", "....":"h", "..":"i", ".---":"j", "-.-":"k", ".-..":"l",
"--":"m", "-.":"n", "---":"o", ".--.":"p", "--.-":"q", ".-.":"r",
"...":"s", "-":"t", "..-":"u", "...-":"v", ".--":"w", "-..-":"x",
"-.--":"y", "--..":"z", "-----":"0", ".----":"1", "..---":"2",
"...--":"3", "....-":"4", ".....":"5", "-....":"6", "--...":"7",
"---..":"8", "----.":"9", ".-.-.-":".", "--..--":",", "..--..":"?",
".----.":"\'", "-.-.--":"!", "-..-.":"/", "-.--.":"(", "-.--.-":")",
".-...":"&", "---...":":", "-.-.-.":";", "-...-":"=", ".-.-.":"+",
"-....-":"-", "..--.-":"_", ".--.-.":"@", ".-..-.":"\"", "...-.":"*",
"-.-.-":"\\", "---.-":"%", "--.-.":"#", "--.-.-":"|", "......":"^",
".---..":"~", "-..-.-":"`", "...-..":"$", ".--..":"[", ".--..-":"]",
".--.-":"{", ".--.--":"}", "-.---":"<", "-.----":">", "..--":" ",
".-.-":Keycode.ENTER, "----":Keycode.BACKSPACE, "....-.":Keycode.SHIFT,
".-----":Keycode.CONTROL, "..----":Keycode.ALT, "...---":Keycode.ESCAPE }
key = digitalio.DigitalInOut(board.D4)
key.direction = digitalio.Direction.INPUT
key.switch_to_input(pull=digitalio.Pull.UP)
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard)
while True:
dit = 0.16
daw = 3 * dit
pauselength = 6 * dit
pauseduration = 0.0
keypressed = False
pause = False
stack = ""
while True:
if not key.value and not keypressed:
# key press detected
starttime = time.monotonic_ns()
keypressed = True
elif key.value and keypressed:
# key depressed, measure time
duration = (time.monotonic_ns() - starttime)/1e9
if duration <= dit:
stack += "."
elif duration <= daw:
stack += "-"
keypressed = False
sleepstart = time.monotonic_ns()
pause = True
if key.value and not keypressed and pause:
pauseduration = (time.monotonic_ns() - sleepstart)/1e9
if pauseduration > daw and pauseduration < pauselength:
if stack in lookup: # Buchstaben gefunden
k = lookup[stack]
if isinstance(k, str): # printable?
keyboard_layout.write(k)
keyboard.release_all() # automatically unlatches
elif k in (Keycode.SHIFT, Keycode.CONTROL, Keycode.ALT):
# Let's latch! Control code...
keyboard.press(k)
else:
# Keycode.ESCAPE, RETURN oder BACKSPACE
keyboard.press(k)
keyboard.release_all()
stack = ""
else:
# Hab vergessen, was das macht...
stack = ""
elif pauseduration >= pauselength:
# Wortende, Leerzeichen schreiben. Lassen wir nun weg.
stack = ""
#keyboard_layout.write(" ")
pause = False
time.sleep(0.025)
Listing 1: Morse parser and USB HID keyboard implementation