Morseboard

Was ist das?

Morseboard ist eine altmodische Morsetaste mit USB-Anschluss. Steckt man sie an einen modernen PC so meldet sie sich als USB-Tastatur an und es ist möglich Texte per Morsecode einzugeben.

Die Idee dazu habe ich von Mitxela, der zwei Varianten des Konzepts implementiert hat (Morse Code USB Keyboard, Morse Code USB Keyboard Mk II). Er ist aber nicht er einzige oder erste, der so etwas gebaut hat.

Hardware

Meine Version setzt mehr auf High-Level-Software als Mitxelas typische winzige und hocheffiziente Hardware. Ich bin faul und löte nicht gerne unter dem Mikroskop. Deshalb basiert Morseboard auf dem Digispark-Board.

Digispark enthält einen ATTiny85, denselben Controller den Mitxela verwendet hat, fügt aber einen Bootloader, Bibliotheken für die USB-Unterstützung und Integration in das Arduino-Ökosystem hinzu. Damit ist der Einstieg in die Programmierung trivial und ich kann mich auf die für mich interessanteren Teile konzentrieren.

Meine Morsetaste eine K40 aus DDR-Produktion und damit hinreichend „vintage“. Außerdem ist sie preiswert erhältlich.

Vorteilhaft für mich ist, daß die K40 im Fuß genug Platz für das Digispark-Board bietet. Außerdem passt dort ein Piezo-Summer den ich von einem toten PC-Motherboard gepflückt habe. Vervollständigt wird die Hardware durch ein USB-Kabel im geflochtenen Textil-Look.

Die zusätzliche Schaltung ist nicht der Rede wert: Der Kontakt der Morsetaste wird an einen der GPIO-Pins angeschlossen und über einen Vorwiderstand an Masse gelegt. Wird die Taste betätigt zieht sie den Pin also auf LOW. Der Buzzer kommt an eine anderen GPIO-Pin und geht auch gehen Masse.

Ich habe alles fliegend verlötet, mit Isolierband umwickelt und mit dem obligatorischen Heißkleber im Sockel der Taste montiert. Um das Kabel einführen zu können habe ich das Plastik des Micro-USB-Steckers so lange weggeschnitzt bis der durch die werksseitige Öffnung gepasst hat. Ein Knoten im Kabel dient als Zugentlastung.

Morsecode

Der Morsecode überträgt Zeichen als lange und kurze Signale mit Pausen dazwischen. Er verwendet technisch gesprochen also die einfachste Form der Amplitudenumtastung, das On-Off-Keying OOK.

Die Synchronisation von Sender und Empfänger erfolgt über ein vereinbartes Zeitraster basierend auf der Länge des kurzen Signals als Einheit, genannt ein „Dit“. Die Pause zwischen kurzen und langen Symbolen soll genauso lang sein wie ein Dit. Das lange Symbol „Dah“ wird dreimal so lange gesendet. Das Ende eines Textzeichens wird durch eine Pause von drei Dit angezeigt, ein Wort endet mit einer Pause von sieben Dit.

Der Code selber ist ein Huffmann-Code: Häufige Zeichen wie das E und T werden mit nur einem Symbol übertragen, seltenere mit längeren Folgen.

Entwickelt zum Senden und Empfangen per Hand und Ohr wurde der Code im Laufe seiner langen Geschichte immer wieder weiterentwickelt und erfreut sich auch heute noch bei Funkamateuren großer Beliebtheit.

Software

Der Arduino-Sketch zum Betrieb des Digispark als Morseboard steht auf GitHub bereit.

Allgemeine Struktur

Die Software besteht aus mehreren Teilen. Unter meinem Code wohnt ein Bootloader von Digispark der für die einfache Programmierung über USB sorgt, die DigiKeyboard-Bibliothek die die Funktionalität als USB-Tastatur implementiert und in die Arduino-Welt bringt.

Dieser Unterbau ist eine Black-Box und funktioniert einfach. Für mich bleibt also nur das übliche Arduino-Tänzchen von setup() und loop().

In setup() werden die I/O-Pins des ATTiny85 programmiert so daß der Code den Zustand der Morsetaste lesen und die On-Board-LED sowie den Buzzer ansteuern kann.

In loop() wird zunächst mit DigiKeyboard.update() dafür gesorgt, dass die USB-Kommunikation reibungslos läuft.

Dann wird der aktuelle Zustand der Morsetaste ausgelesen. Der muss entprellt werden, dazu verwende ich das Arduino-Standardbeispiel. Der entprellte aktuelle Zustand wird in einer globalen Variable keyState abgelegt.

Außerdem werden die LED und der Buzzer ein- und ausgeschaltet und folgen damit dem Zustand der Taste.

Der Zustandsautomat

MorseBoard muss agieren wenn die Taste gedrückt und wenn sie losgelassen wird. Es muss jeweils die Zeiten nehmen und an den entsprechenden Stellen Aktionen wie das Dekodieren eines Buchstaben aus einer Folge von Morse-Symbolen und das Senden von Tastendrücken an den Host auslösen.

Dieses Verhalten habe ich mit einem klassischen Zustandsautomaten implementiert. Der hat vier eigene Zustände, einer davon wird noch durch das Vorliegen oder Fehlen von Symbolen logisch unterteilt.

Für jeden der Zustände gibt es eine behandelnde Funktion im Code und in loop() wird einfach nur in jedem Durchlauf aus einer Tabelle die passende Funktion zum aktuellen Status aufgerufen. Die verschiedenen Zustände orchestrieren den Ablauf von Dits und Dahs, Zeichen- und Wortpausen.

Decoder

Wenn der Morsegeber nach ein paar Dits und Dahs eine Pause von drei Dits einlegt, so zeigt das an, dass ein Buchstabe komplett gegeben wurde. Der Code muss nun diese in einem Puffer vorliegende Folge von Dits und Dahs in einen Tastendruck auf der USB-Tastatur umsetzen.

Anstatt eine große Tabelle zu bauen habe ich mich entschieden die Huffmann-Eigenschaft des Morsecodes auch sichtbar zu machen:

Baum zur Dekodierung von Morsezeichen (Wikimedia)

Die Zeichen sind logisch in einem binären Baum angeordnet und jedes Dit oder Dah verzweigt links oder rechts. Das Ende der Folge kann auch in einem inneren Knoten liegen und wird dann durch das Nullbyte am Ende des Puffers angezeigt.

Im Code entsteht ist der Baum als eine lange geschachtelte if-then-else-Folge repräsentiert:

Mir gefällt, dass dieser objektiv grauenhaft anzusehende Code begründbar die korrekte Wahl zur Implementation dieses Features ist.

Erweiterungen

Gegenüber dem reinen Morsecode habe ich zusätzlich eine Backspace-Funktion implementiert: Wenn die Morsetaste für eine Wortpause von sieben Dit oder länger gehalten wird, so sendet Morseboard ein Backspace.

Der Buzzer kann mit der Num-Lock-Taste auf einer anderen Tastatur aktiviert und ausgeschaltet werden.

Mit Scroll-Lock kann man den Decoder deaktivieren und bekommt dann Morsecode in Form von Punkten und Strichen übertragen.