von Ralf Beesner, DK5BU
Elektronik-Labor Projekte AVR
robbi login:
M
password:
login incorrect
robbi login:
M
++
LS
hello.txt profile vertrag.txt
++
CAT HELLO.TXT
this is slackware 13.1 morse shell
how are you ?
have fun.
++
EXIT
abgemeldet
'
' Programm gibt über die serielle Schnittstelle eingehende Zeichen akustisch als Mosecode aus und
' sendet über die Paddles eingegebenen Morsecode auf die serielle Schnittstelle
'
' Die Tonhöhe ist fest eingestellt.
'
' Pin PB0 wird als Timer0-Ausgang OC0a verwendet, Ton wird durch Umschalten des
' Pins als Eingang / Ausgang ein- und ausgeschaltet
'
' Das Paddle für die Eingabe der Morsezeichen liegt an PB3 (Punktkontakt) und PB4 (Strichkontakt)
'
' Pin PB1 und PB2 bilden einen Software- UART (eingetippte Zeichen werden aber nicht als Echo auf das Terminal
' zurückgesendet)
'
' Version mit Terminalbuffer: Pegeländerungen am seriellen Eingang lösen einen Interrupt aus. Die Zeichen werden
' im Hintergrund in einen FIFO geschrieben und durch die Morseroutine Zug um Zug ausgelesen.
' Der FIFO speichert 178 Zeichen.
' Damit der Buffer scvhnell genug ist, Taktrate 8 MHz OHNE Vorteiler
'
'
' Der FIFO nutzt die Overlay- Funktionalität. Der FIFO wird mit den komfortablen String- Manipulationsbefehlen
' bearbeitet; das Auslesen des ältesten Zeichens im FIFO erfolgt jedoch direkt als Byte statt als 1-Zeichen-String;
' das erspart die Umwandlung String -> Byte
'
' Version 2 fragt nach Reset erst mal die gewünschte Geschwindigkeit ab. Sendegeschwindigkeit ist geringer (2/3)
'
' Version 2a vermindert die Anforderungen an die Gebepräzision; auch bei kleinen Pausen zwischen Punkt und Strich
' wird auf ein gemeinsames Zeichen erkannt
' Version 3 sendet bei Pause > 5 Punkte genau ein Leerzeichen auf des Terminal
'
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'
' Grundeinstelllungen:
$regfile = "ATtiny45.dat"
$crystal = 8000000 ' interner RC-Oszillator, KEIN Vorteiler
$hwstack = 40 ' 32 Byte wegen Interrupt + 8 bBytes für max.4 Unterprogramme
$swstack = 0
$framesize = 0
Baud = 9600
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'Variablen und Konstanten dimensionieren:
'
Dim Recbyte As Byte
Dim Recchar As String * 1
Dim I As Byte 'Für temporären Gebrauch als Schleifenzähler
Dim J As Byte
Dim K As Byte ' ''
Dim Z As Byte ' Z=1, wenn bereits ein Leerzeichen gesendet wurde
Dim M As Byte ' Index des aktuellen Morsebuchstabens in unserer Tabelle
Dim L As Byte ' für niederwertigstes Bit beim bitweisen Erzeugen des Morsezeichens
Dim D As Byte ' Morsebyte in der Decodierroutine
Dim P As Byte ' Punktspeicher-Bit der Decodierroutine
Dim E As Byte ' resultierendes ACCII-Byte der Decodierroutine
Dim Pufferstring As String * 178
Dim Puffer(3) As Byte At Pufferstring Overlay
Dim Txtstring As String * 4
Dim Txt(4) As Byte At Txtstring Overlay
Dim T As Byte
Const Tonhoehe1 = 25 ' Tonhöhe
Const Tonhoehe2 = 40
Dim G(2) As Word
Dim Punktlaenge1 As Word ' Punktlänge in "Empfangsrichtung"
Dim Punktlaenge2 As Word ' Punktlänge in "Senderichtung"
Dim Punktachtel As Word
Dim Strichlaenge1 As Word ' Strichlänge
Dim Strichlaenge2 As Word
Dim Wortpause1 As Word ' Länge Wortpause
Dim Wortpause2 As Word
'
Buzzer Alias Ddrb.0
Punktkontakt Alias Pinb.3
Strichkontakt Alias Pinb.4
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'Initialisierung des Programms:
'
'
' Morseton mit Timer0 erzeugen:
'
' Timer0 zählt das Register TCNT0 hoch. Es wird mit Register OCR0A verglichen.
' Wenn TCNT0 = OCR0A, wird Output OC0A/PB0 umgeschaltet (getoggled)
' Timer0 erzeugt so Dauerton; er wird jedoch nur an den Ausgangspin durchgeschaltet,
' wenn das Datenrichtungs- Register DDRB.0 = 1 ist. Bei 0 wird der Ton unterdrückt.
'
Config Timer0 = Counter , Prescale = 1024 , Compare A = Toggle , Clear Timer = 1
Acsr.acd = 0 ' Analog-Komparator ausschalten, spart etwas Strom
Pcmsk.2 = 1 ' PCINT für Port B.2 freigeben
Gimsk.5 = 1 ' PCints aktivieren
Sreg.7 = 1 ' Interrupts gernerell freigeben
Portb = &B00011000 ' Pullups für Strich- und Punktkontakt
Ddrb = &B00000000 ' erstmal alles Eingang
Open "comb.2:9600,8,n,1,inverted" For Input As #1 ' Software- UART Input an PortB.2
Open "comb.1:9600,8,n,1,inverted" For Output As #2 ' Software- UART Output an PortB.1
On Pcint0 Seriellelesen
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Speed:
' vorläufige Werte
Punktlaenge1 = 80 ' Punktlänge in "Empfangsrichtung"
Punktlaenge2 = 100 ' Punktlänge in "Senderichtung"
Punktachtel = 20
Strichlaenge1 = Punktlaenge1 * 3 ' Strichlänge
Strichlaenge2 = Punktlaenge2 * 3
Wortpause1 = Punktlaenge1 * 5 ' Länge Wortpause
Wortpause2 = Punktlaenge2 * 5
' Wunschgeschwindigkeit abfragen; Eingabe 2-stellig
Ocr0a = Tonhoehe1
Txtstring = "WPM?"
Gosub Sendmorsestring
I = 0
Do
If Punktkontakt = 0 Or Strichkontakt = 0 Then ' Punkt - oder Strichkontakt gedrückt
I = I + 1
Gosub Decodekeyer
G(i) = Val(e) ' jeweils einstellige Zahl abholen
End If
Loop Until I = 2
' Aus dem abgefragten Wert neue Geschwindigkeit berechnen
G(1)1 = 10 * G(1) ' Zehnerstelle WPM
G(1) = G(1) + G(2) ' Einerstella addieren
Punktlaenge1 = 1320 / G(1) ' aus WPM Punkitlänge errechnen
Strichlaenge1 = Punktlaenge1 * 3
Wortpause1 = Punktlaenge1 * 5
Punktlaenge2 = 3 * Punktlaenge1 ' Sendegeschwindigkeit soll nur 2/3 der
Punktlaenge2 = Punktlaenge2 / 2 ' Empfangsgeschwindigkeit sein
Punktachtel = Punktlaenge2
Shift Punktachtel , Right , 3 ' Achtel- Punkt
Strichlaenge2 = Punktlaenge2 * 3
Wortpause2 = Punktlaenge2 * 5
Ocr0a = Tonhoehe1
If G(1) < 10 Or G(1) > 30 Then ' auf plausiblen Wert prüfen
Txtstring = "rpt " ' meckern
Gosub Sendmorsestring
Goto Speed ' Geschwindigkeitsabfrage wiederholden
End If
' wenn Geschwindigkeit plausibel, "ok" senden
Txtstring = "ok "
For T = 1 To 3
M = Asc(txt(t))
M = Lookup(m , Morsetabelle) ' Morsezeichen aus Tabelle holen
Gosub Morse
Next T
Main:
Do
Gosub Zeichenlesen
If Punktkontakt = 0 Or Strichkontakt = 0 Then ' Punkt - oder Strichkontakt gedrückt
Gosub Decodekeyer
Put #2 , E ' aufs Terminal senden
Z = 0 ' Leerzeichenflag zurücksetzen
If D <> 45 Then ' an ein Return darf kein Leerzeichen angehängt werden
Gosub Leerzeichenpruefg
End If
End If
Loop
Zeichenlesen:
Ocr0a = Tonhoehe1
If Puffer(1) = 0 Then ' Puffer leer
Return
End If
M = Asc(puffer(1)) ' Ascii- Wert des untersten Zeichens im Puffer ermitteln
M = Lookup(m , Morsetabelle) ' Morsezeichen aus Tabelle holen
Gosub Morse
Pufferstring = Mid(pufferstring , 2) ' das unterste Zeichen im Pufferstring entfernen
Return
' Morsezeichenerzeugung:
Morse:
If M = 0 Then ' Sonderfall: Leerzeichen;
Waitms Wortpause1
Goto Zeichenende
End If
For I = 1 To 8
If M = 1 Then ' Das Byte hat nur noch den Wert 1; Zeichenende!
Goto Zeichenende
End If
L = M And &B00000001 ' niederwertigstes Bit lesen
Buzzer = 1
If L = 1 Then
Waitms Strichlaenge1 ' ist das Bit 1 -> dah
Else
Waitms Punktlaenge1 ' ist das Bit 0 -> dit
End If
Buzzer = 0
Waitms Punktlaenge1 ' Pause innerhalb des Morsezeichens
Shift M , Right , 1 ' Bits um eine Stelle nach rechts shiften
Next I
Zeichenende:
Waitms Strichlaenge1 ' Pause zwischen Morsezeichen
Return
Seriellelesen:
Pcmsk.2 = 0 ' Solange Bits reinkommen, PCINT sperren
Get #1 , Recbyte ' Byte lesen
' Put #2 , Recbyte ' Byte auf Terminal senden (Echo)
Recchar = Chr(recbyte) ' Byte in ASCII- Zeichen wandeln
Pufferstring = Pufferstring + Recchar ' ASCII- Zeichen ans Ende des Pufferstrings anhängen
Pcmsk.2 = 1 ' PCINT wieder freigeben
Return
Decodekeyer: ' Prinzip: eine 1 wird in der Variablen "K" von links nach rechts geschoben.
' nur wenn Strich gedrückt wurde, wird die 1 in die Variable D übernommen
Ocr0a = Tonhoehe2
D = 0
K = 1
Do
If Punktkontakt = 0 Then ' Punktkontakt gedrückt
Buzzer = 1 ' Ton an
Waitms Punktlaenge2
Buzzer = 0 ' Ton aus
Waitms Punktlaenge2
Shift K , Left ' Byteinhalt wandert 1 Stelle nach links, von rechts wird eine "0" eingeschoben
End If
Mark:
If Strichkontakt = 0 Then ' Strichkontakt gedrückt
Buzzer = 1 ' Ton an
Waitms Strichlaenge2
D = D + K ' die 1 für den Strich wird in die Variable "D" übernommen
Shift K , Left ' Byteinhalt wandert 1 Stelle nach rechts, von links eine "0" eingeschoben
If Punktkontakt = 0 Then
P = 1 ' wenn Punktkontakt ebenfalls gedrückt
End If ' Punktspeicher setzen
Buzzer = 0 ' Ton aus
Waitms Punktlaenge2
If P = 1 Then ' Punktspeicher prüfen
Buzzer = 1 ' Ton an
Waitms Punktlaenge2
Buzzer = 0 ' Ton aus
Waitms Punktlaenge2
Shift K , Left ' Byteinhalt wandert 1 Stelle nach links, rechts wird 0 eingeschoben
P = 0 ' Punktspeicher zurücksetzen
Goto Mark ' Prüfen, ob Strichkontakt bereits wieder gedrückt
End If
End If
J = 0
Do ' wir warten max. halbe Punktlänge, um unexakte Gebeweise abzufangen
If Punktkontakt = 0 Or Strichkontakt = 0 Then ' vorzeitiger Ausstieg, wenn Punktkontakt oder Strichkontakt gedrückt
Exit Do
End If
Waitms Punktachtel
J = J + 1
Loop Until J = 4 ' Abbruch bei halber Punktlänge
Loop Until Punktkontakt = 1 And Strichkontakt = 1 ' kein Kontakt mehr gedrückt; Morsezeichen fertig
D = D + K ' eine 1 wird als Endbit angehängt
E = Lookdown(d , Morsetabelle , 128) ' inverse Lookup in der Tabelle, um den zugehörigen Ascii- Wert zu ermitteln
E = E - 1 ' Data- Elemente werden ab 1 gezählt, Ascii- Tabelle beginnt bei Null
If E > 64 Then ' "lookdown" findet stets die Grossbuchstaben.
E = E + 32 ' Wir wollen Kleinbuchstaben (wichtig für Linux)
End If
Return
Leerzeichenpruefg:
I = 0
If Z = 0 Then ' noch kein Leerzeichen auf Terminal gesendet
Do
If Punktkontakt = 0 Or Strichkontakt = 0 Then ' Abruch, wenn Punkt- oder Strichkontakt gedrückt
Exit Do
End If
Waitms Punktachtel
I = I + 1
Loop Until I = 48 ' 48 Achtel = 6 Punktlängen
If I = 48 Then
Put #2 , &H20 ' Leerzecihen auf Terminal
Z = 1 ' Flag, dass Leerzeichen gesendet wurde
End If
End If
Return
Sendmorsestring:
For T = 1 To 4 ' Textstring "WPM ?" ausgeben
M = Asc(txt(t))
M = Lookup(m , Morsetabelle) ' Morsezeichen aus Tabelle holen
Gosub Morse
Next T
Return
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Morsetabelle:
'Ascii 0 - 32 ; hier wird nur Linefeed in <kn> umgesetzt
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , &B00101101 , 0 , , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 0 , 0 , 0
' Ascii 32 - 47 -> _!"#$%&'()*+,-./
Data 0 , 0 , &B01010010 , 0 , 0 , 0 , 0 , 0 , &B00101101 , &B01101101 , 0 , &B00101010 , &B01110011 , &B01100001
Data &B01101010 , &B00101001
'Ascii 48 - 57 -> 0123456789
Data &B00111111 , &B00111110 , &B00111100 , &B00111000 , &B00110000 , &B00100000 , &B00100001 , &B00100011 , &B00100111 , &B00101111
'Ascii 58 - 64 -> :;<=>?@
Data &B01000111 , &B01110011 , &B00101101 , &B00110001 , &B01101101 , &B01001100 , 0
'Ascii 65 - 90 ABCDEFGHIJKLMNOPQRSTUVWXYZ
Data &B00000110 , &B00010001 , &B00010101 , &B00001001 , &B00000010 , &B00010100 , &B00001011 , &B00010000 , &B00000100
Data &B00011110 , &B00001101 , &B00010010 , &B00000111 , &B00000101 , &B00001111 , &B00010110 , &B00011011 , &B00001010
Data &B00001000 , &B00000011 , &B00001100 , &B00011000 , &B00001110 , &B00011001 , &B00011101 , &B00010011
'Ascii 91 - 96 -> Muell
Data 0 , 0 , 0 , 0 , 0 , 0
' Ascii 97 - 122 abcdrfghijklmnopqrstuvwxyz
Data &B00000110 , &B00010001 , &B00010101 , &B00001001 , &B00000010 , &B00010100 , &B00001011 , &B00010000 , &B00000100
Data &B00011110 , &B00001101 , &B00010010 , &B00000111 , &B00000101 , &B00001111 , &B00010110 , &B00011011 , &B00001010
Data &B00001000 , &B00000011 , &B00001100 , &B00011000 , &B00001110 , &B00011001 , &B00011101 , &B00010011
'Ascii 123 - 127 -> Muell