Ein inverses AVR-Morsekeyboard


von Ralf Beesner  
Elektronik-Labor   Projekte   AVR 



Vor ca. 20 Jahren kamen einige Morsekeyboards auf den Markt, mit denen man mittels einer "Schreibmaschinentastatur" Morsezeichen erzeugen konnte (ich konnte mich aber nie an die Dinger gewöhnen).

Unter Verwendung des "serial keyboards" http://hobby-electrons.sourceforge.net/projects/terminal-keyboard/ habe ich mir nun die umgekehrte Lösung gebaut: eine Schaltung, die Morsezeichen in Tastaturanschläge umwandelt, so dass man per Morsetaste in Anwendungen, die auf dem PC laufen, hineinschreiben kann. So seine Texte einzugeben ist zwar mühsam und weitgehend sinnfrei, aber ich finde, dass es dennoch eine coole Spielerei ist ;-)

Da ich mit der Programmiersprache "C" auf Kriegsfuß stehe, wandelt ein in Bascom programmierter ATtiny13 die Morsezeichen zunächst in ein serielles Signal; dieses wird dann durch das mit einem ATtiny2313 realisierte virtuelle HID-Keyboard in ein USB-Keyboard-Signal aufbereitet.

 

Hardware

 

Die Aufteilung auf zwei Mikrocontroller ist etwas unelegant, erfordert aber außer dem zweiten Controller keine Bauteile, die nicht ohnehin erforderlich wären. Der ATtiny13 übergibt das serielle Signal ohne Interface-Schaltung direkt an den seriellen Eingang des ATtiny2313. Die übrigen Pins des Attiny 13 sind mit der Morsetaste, einem Buzzer für den Mithörton und zwei Schalterchen für die Wahl des (Morse-) Geschwindigkeitsbereiches und des Modus für die Leerzeichen beschaltet.

Die gesamte Schaltung wird mit ca. 3,3 V betrieben, die mit einer in Durchlassrichtung betriebenen roten LED aus dem USB gewonnen werden.

Leider erfordert das "serial keyboard" einen Hardware-UART, deshalb muss man sich mit dem 20-poligen ATtiny2313 herumschlagen, obwohl die meisten Pins nicht benötigt werden.

Das Foto des Versuchsaufbaus weicht etwas von Schaltplan ab; an der grauen WAGO-Klemme liegen u.a. noch zwei Eingänge für ein RS232-Signal bzw. ein TTL-Signal, so dass sich auch andere serielle Signale mit dem "serial keyboard" umwandeln lassen.

 

Bascom-Software

Die ATtiny13-Software beruht auf morse.bas von Burkhard Kainka, das auf ein Atmel Butterfly mit dem ATmega169 zugeschnitten war und das ich vor einiger Zeit auf den ATmega8 portiert hatte -siehe Morsedecoder.html .

Neben der Umstellung von der LCD-Ausgabe auf die serielle Ausgabe war es erforderlich, den Zugriff auf die Morsezeichentabelle RAM-sparender zu lösen, da der AtMega 8 immerhin 1024 Byte SRAM hat, der AtTiny 13 jedoch nur 64.

Eine weitere Änderung betrifft die Leerzeichenerzeugung; es gibt keinen speziellen Morsecode dafür, ein Leerzeichen wird lediglich durch eine kleine Gebepause übermittelt. Zunächst hatte ich Leerzeichen nur aufgrund dieser Gebepausen definiert, aber in der Praxis führt das dann dazu, dass häufig Leerzeichen an den falschen Stellen eingefügt werden -ein PC ist ja nicht so semantisch begabt, dass er das wie ein menschlicher Operator "zurechtinterpretieren" kann.

Die Pause-Leerzeichenerkennung ist daher abschaltbar, und als Code für ein Leerzeichen habe ich das Verkehrszeichen <as> definiert. Da es auch kein Morsezeichen für <carriage return> gibt, musste dafür das Verkehrszeichen <kn> herhalten (Verkehrzeichen bestehen meist aus zwei zusammengezogenen Morsezeichen und kennzeichnen Spruchbeginn, Spruchende und dergleichen).   

Das Verkehrszeichen "Irrung" (eigentlich 8 Morsepunkte, hier nur 6 oder 7 Morsepunkte, denn die Zeichenlänge ist auf maximal 7 Morsepunkte begrenzt) erzeugt ein <backspace>; der Cursor wird um einen Schritt zurückgesetzt und das darunterliegende Zeichen gelöscht. So kann man Falscheingaben korrigieren.

Es findet keine gleitende Anpassung an die Morsegeschwindigkeit statt; mit einem weiteren Schalter kann man lediglich zwischen 60 und 90 Zeichen pro Minute wählen. Der "Fangbereich" der Software reicht aber von 40 bis 90 Zeichen pro Minute bzw. 60 bis 120 Zeichen pro Minute, so dass die zwei Bereiche die üblicherweise mit "straight keys" erzielbaren Gebegeschwindigkeiten abdecken.

C-Software

Die "eingedeutschte Version" des "serial keyboards" hatte ich bereits in einem anderen Beitrag beschrieben; das Softwarepaket ist hier beigefügt. Mit besseren C-Kenntnissen ließe sich die Bascom-Software nach C portieren und mit dem  VUSB-Treiber zusammenfassen. Da dann die Notwendigkeit eines Hardware-UART entfiele, dürfte ein ATtiny45 reichen, so dass die Hardware (selbst bei Verwendung eines AtTiny im DIP-Gehäuse) auf die Größe eines USB-Sticks schrumpft - damit wäre sie dann noch etwas cooler...

 Download: morsekeyboard-soft.zip

 '-----------------------------------------------------------------------------------------
' Software bases on:
' Burkhard Kainka
' morse.bas
' morse code decoder with Mega169 and LCD butterfly driver
' using butterfly joystick as morse key


' screwed up by Ralf Beesner, DK5BU

' shrinked to fit into AtTiny13 and changed for ASCII output by software UART
' some keycodes have been added, e.g. + - ? ( ) . ,
' and, most important keycode: space between words ;-)
' all timing constants are derived from the duration of a short morse element ("dit"), so its easier
' to change speed

' there are two ways to insert spaces: by simply waiting (look at mainloop for variable "iconst")
' or by a dedicated character (morsecode <AS>; wait a second) which is better for talking to a computer

' Return (ASCII 13) is generated by the morsecode <KN>
' Backspace (ASCII 8) is generated by morsecode Error (...... and .......).
' Only 6 or 7 dots are recognized as error character (maximum possible length.of a character is 7)

' Buzzer is attached to PB0
' Keyer is attached to PB2
' Speed switch is attached to PB3 (60 or 90 characters per minute)
' Space switch is attached to PB4 (inserts space by idling time or only by character <AS>

'-----------------------------------------------------------------------------------------

$regfile = "Attiny13.dat" ' specify the used micro
$crystal = 1200000 ' used clock frequency
$hwstack = 32 ' default use 32 for the hardware stack
$swstack = 12 ' default use 10 for the SW stack
$framesize = 0 ' default use 40 for the frame space



Dim Key As Byte
Dim C As Byte
Dim Timepressed As Word
Dim Timenotpressed As Word
Dim Charactercode As Byte
Dim Idling As Word
Dim Speed As Byte


Dim Dithalf As Word
Dim Tpconst As Word
Dim Tnpconst As Word
Dim Iconst As Word

Declare Sub Getkey
Declare Sub Getkeytimes
Declare Sub Initcode
Declare Sub Printdisplay



Portb = &B00011100 ' pullups for PB2,PB3,PB4
Ddrb = &B00000010 ' PB1 is UART output, all other pins are inputs
Didr0 = &B0000011 ' inputs PB0 and PB1 are deactivated

' Timer 0 is configured for Sound at OC00A / PB0

Config Timer0 = Timer , Prescale = 256 , Compare A = Toggle , Clear Timer = 1
Pwm0a = 10


' software UART
Open "comb.1:9600,8,n,1" For Output As #1



Do

' setting of speed

If Pinb.3 = 0 Then
Dithalf = 33 ' duration of half a dit in ms; speed is 90 characters / min. '
Else
Dithalf = 50 ' duration of half a dit in ms; speed is 60 characters / min.
End If

Tpconst = Dithalf * 3 ' 1.5 * Dit; maximum tinme for a dit
Tnpconst = Dithalf * 4 ' 2 * Dit; minimum time for a dah
Iconst = Dithalf * 6 ' space between words


Charactercode = 1

Do
Getkeytimes

If Idling > Iconst And Pinb.4 = 0 Then ' inserts space between morse words
Gosub Printdisplay ' may be deactivated if you want to insert spaces only by <AS>
End If

Shift Charactercode , Left , 1
If Timepressed > Tpconst Then
Incr Charactercode
End If
Loop Until Timenotpressed > Tnpconst
Gosub Printdisplay

Loop




Sub Printdisplay
Restore Morsetable
C = Lookup(charactercode , Morsetable)

If C > 64 Then ' may be deactivated if you want capital letters
C = C + 32 ' transforms capital letters into small letters
End If

Put #1 , C ' ASCII output via software UART
End Sub




Sub Getkey
Key = Not Pinb.2 ' Key is attached to PB2, if key pressed -> low
If Key > 0 Then
Ddrb.0 = 1
Else
Ddrb.0 = 0
End If
End Sub




Sub Getkeytimes
Timepressed = 0
Timenotpressed = 0
Idling = 0
Do
Getkey
Waitms 1
Idling = Idling + 1
Loop Until Key > 0

Do
Waitms 1
Timepressed = Timepressed + 1
Getkey
Loop Until Key = 0
Do
Waitms 1
Timenotpressed = Timenotpressed + 1
Getkey
Loop Until Key > 0 Or Timenotpressed > Tnpconst
End Sub





Morsetable:
Data 0 ,
Data 32, ' "space" 00000001 ASCII 32
Data 69, ' "E", . , 00000010, ASCII 69
Data 84, ' "T", - , 00000011, ASCII 84
Data 73, ' "I", .. , 00000100, ASCII 73
Data 65, ' "A", .- , 00000110, ASCII 65
Data 78, ' "N", -. , 00000110, ASCII 78
Data 77, ' "M", -- , 00000111, ASCII 77
Data 83, ' "S", ... , 00001000, ASCII 83
Data 85, ' "U", ..- , 00001001, ASCII 85
Data 82, ' "R", .-. , 00001010, ASCII 82
Data 87, ' "W", .-- , 00001011, ASCII 87
Data 68, ' "D", -.. , 00001100, ASCII 68
Data 75, ' "K", -.- , 00001101, ASCII 75
Data 71, ' "G", --. , 00001110, ASCII 71
Data 79, ' "O", --- , 00001111, ASCII 79
Data 72, ' "H", .... , 00010000, ASCII 72
Data 86, ' "V", ...- , 00010001, ASCII 86
Data 70, ' "F", ..-. , 00010010, ASCII 70
Data 0,
Data 76, ' "L", .-.. , 00010100, ASCII 76
Data 0 , '
Data 80, ' "P", .--. , 00010110, ASCII 80
Data 74, ' "J", .--- , 00010111, ASCII 74
Data 66, ' "B", -... , 00011000, ASCII 66
Data 88, ' "X", -..- , 00011001, ASCII 88
Data 67, ' "C", -.-. , 00011010, ASCII 67
Data 89, ' "Y", -.-- , 00011011, ASCII 89
Data 90, ' "Z", --.. , 00011100, ASCII 90
Data 81, ' "Q", --.- , 00011101, ASCII 81
Data 0,
Data 0,
Data 53, ' "5", ..... , 00100000, ASCII 53
Data 52, ' "4", ....- , 00100001, ASCII 52
Data 0,
Data 51, ' "3", ...-- , 00100011, ASCII 51
Data 0,
Data 0,
Data 0,
Data 50, ' "2", ..--- , 00100111, ASCII 50
Data 32, ' "as" .-... , 00101000, ASCII 32
Data 0,
Data 43, ' "+" .-.-. , 00101010 ASCII 43
Data 0,
Data 0,
Data 0,
Data 0,
Data 49, ' "1", .---- , 00101111, ASCII 49
Data 54, ' "6", -.... , 00110000, ASCII 54
Data 61, ' "=" -...- , 00110001, ASCII 61
Data 47, ' "/" -..-. , 00110010, ASCII 47
Data 0,
Data 0,
Data 0,
Data 13, ' "kn" -.--. , 00110110 ASCII 13 (Return)
Data 0,
Data 55, ' "7", --... , 00111000, ASCII 55
Data 0,
Data 0,
Data 0,
Data 56, ' "8", ---.. , 00111100, ASCII 56
Data 0,
Data 57, ' "9", ----. , 00111110, ASCII 57
Data 48, ' "0", ----- , 00111111, ASCII 48
Data 8, ' "......" , 01000000, ASCII 8 (Backspace)
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 63, ' "?", ..--.. , 01001100, ASCII 63
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 34 , ' "'" .-..-. , 01010010, ASCII 34
Data 0,
Data 0,
Data 46, ' ".", .-.-.- , 01010101, ASCII 46
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 45, ' "-", -....- , 01100001, ASCII 45
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 41, ' ")", -.--.- , 01101101, ASCII 41
Data 0,
Data 0,
Data 0,
Data 0,
Data 0,
Data 44, ' ",", --..-- , 01110011, ASCII 44
Data 0,
Data 0,
Data 0,
Data 0,
Data 58, ' ":", ---... , 01111000, ASCII 58
Data 0,
Data 0,
Data 0,
Data 0,
Data 0
Data 0,
Data 0,
Data 8, ' "......." , 10000000, ASCII 8 (Backspace)



Elektronik-Labor   Projekte   AVR