Programm zum Bedienen der Tasten am EPS-103-Gerät (und Steuern der Motoren)
Es ist großartig, beliebige Beschriftungen auf dem Display schreiben zu können. EPS-103 kann uns sagen, was unser Programm tut. Ein weiteres Peripheriegerät, das beherrscht werden muss, ist die Tastatur. Der EPS-103 hat insgesamt 16 Schalter. Allen voran zwei große Knöpfe Up und Down. Unter der sich öffnenden Tür finden wir die Tasten 0 bis 9 und die Taste E. Und einen MODE-Schalter mit drei Positionen, der eigentlich wie drei separate Schalter funktioniert, von denen einer immer dauerhaft geschlossen ist.
Die 16 Schalter sind in einer 4 x 4-Draht-Matrix verdrahtet. Der Eingang der Matrix ist mit Port A der Schaltung 8255A verbunden, d. H. An der Adresse 5800h. Nur die untere Hälfte des Ports ist aktiv. Die oberen vier Bits sind gemäß dem Schema unbenutzt. Hier wäre die Option, die Tastatur um zusätzliche Benutzertasten zu erweitern. Der Ausgang der Matrix wird an Port B der 8255A-Schaltung geleitet, d.h. an die Adresse 5801h. Auch hier sind nur die unteren vier Bits aktiv. Auf der oberen Hälfte des Ports sind die internen Jumper W1, W2 und W3 mit der Bezeichnung Test gemäß dem Diagramm verbunden.
Die Verwendung der Matrix-Tastatur ist ganz einfach. Die Binärzahl 1110 (1101, 1011, 0111) wird in den Eingang geschrieben und dann der Ausgang aus der Matrix gelesen. Anhand seines Binärwerts (1111, 1110, 1101, 1011, 0111) wissen wir, welcher Schalter betätigt wurde. Der Wert 1111 bedeutet, dass keine Taste gedrückt wird. Die folgende Tabelle zeigt die Werte der einzelnen Schalter. Ein Sternchen ersetzt Bits, die die Funktion der Tastatur nicht beeinflussen. Das Programm überschreibt sie normalerweise mit allen Einsen.
Write Address 5800h |
Read Address 5801h |
Button EPS-103 |
MyCode | ||||
bin | hex | bin | hex | 4600h | 4601h | ||
Group 0 | 1111 1110 | 0FE | **** 1110 | 0*E | 1 | 01h | |
**** 1101 | 0*D | 2/E | 02h | ||||
**** 1011 | 0*B | 3/U | 03h | ||||
**** 0111 | 0*7 | 4/W | 04h | ||||
Group 1 | 1111 1101 | 0FD | **** 1110 | 0*E | 5 | 05h | |
**** 1101 | 0*D | 6 | 06h | ||||
**** 1011 | 0*B | 7 | 07h | ||||
**** 0111 | 0*7 | 8/D | 08h | ||||
Group 2 | 1111 1011 | 0FB | **** 1110 | 0*E | 9 | 09h | |
**** 1101 | 0*D | 0 | 0Ah | ||||
**** 1011 | 0*B | E | 0Bh | ||||
**** 0111 | 0*7 | Not used | - | - | |||
Group 3 | 1111 0111 | 0F7 | **** 1110 | 0*E | PRG | 10h | |
**** 1101 | 0*D | TCH | 20h | ||||
**** 1011 | 0*B | RUN + Up | 30h | 0Ch | |||
**** 0111 | 0*7 | RUN + Down | 30h | 0Dh |
Der RUN-Schalter ist etwas anders verdrahtet als die anderen Schalter. Es liegt in Reihe mit den Aufwärts- und Abwärtstasten. Das bedeutet, dass die Verwendung des PRG- oder TCH-Schalters die Up- und Down-Tasten deaktiviert. Daher ist es notwendig, diese drei Tasten und die Auf- und Ab-Tasten in der ersten Schleife zuerst mit ihnen zu identifizieren. Erst anschließend in der zweiten Schleife scannen wir die restlichen Schaltflächen. Nachdem wir die gedrückte Taste identifiziert haben, können wir eine Aktivität starten. Zum Beispiel, um auf dem Display zu schreiben, welche Taste gedrückt wird.
Dieses Programm benötigt RAM, um ausgeführt zu werden. Wir werden den dem Stapel zugewiesenen Speicherplatz verwenden. Der Stack beginnt bei Adresse 4700h und füllt sich zu niedrigeren Werten hin. Deshalb habe ich die Adressen 4600h bis 4603h gewählt. Sie sind ziemlich nah am Stack, sodass die Original-Firmware sie definitiv nicht für etwas anderes verwendet. Gleichzeitig sind sie so weit vom Stackanfang entfernt, dass unser Programm sie bei Verwendung des Stacks nicht mit anderen Daten überschreibt.
Bei Adresse 4600h schreiben wir den Code der gedrückten Taste aus dem Trio PRG, TCH, RUN. Wenn eine der verbleibenden Tasten gedrückt wird, schreiben wir ihren Code an die Adresse 4601h. Es ist nur sinnvoll, den Namen der gedrückten Taste auf dem Display auszudrucken, wenn er sich geändert hat. Daher werden auch die Steueradressen 4602h und 4603h verwendet. Wir kopieren die Werte der Hauptadressen 4600h und 4601h hinein. Durch den Vergleich der Originale und Kopien können wir sehen, ob sich der Status der Tastatur geändert hat.
Tastaturscannen kann Teil des Hauptprogramms sein. Aber normalerweise werden wiederholte Aktionen von einer Art Interrupt behandelt. Der EPS-103 hat einen generierten HW-Interrupt RST7.5 vom Impulsgenerator NE555. Die Impulsdauer und damit die Unterbrechungswiederholung beträgt 4 ms. Dies könnte verwendet werden, um die Tastatur zu bedienen. Wir müssen nur sicherstellen, dass unser Handler beendet wird, bevor der Interrupt erneut ausgelöst wird. Beispielsweise dauert das Löschen des LCD-Displays laut Dokumentation 15 ms. Das bedeutet, dass wir das Display während der Unterbrechung nicht bedienen können.
Aus Studiengründen werden wir den RST7.5-Interrupt verwenden, aber nur, um die Tastatur zu scannen. Das Ergebnis des Scans schreiben wir in das RAM an den Adressen 4600h und 4601h. Es wird eine Schleife im Hauptprogramm geben, die diese Adressen liest und basierend auf dem Inhalt eine Verarbeitung durchführt, einschließlich des Schreibens auf die Anzeige.
Die Einführung des Programms ist die gleiche wie beim Programm Hallo Welt. Wir setzen zuerst die Stack-Adresse im RAM auf 4700h und initialisieren dann die 8255A-Schaltung. Dann müssen wir den Interrupt richtig setzen. RST7.5 muss aktiviert werden, indem 0 auf Bit 2 des Interrupt-Maskenregisters geschrieben wird. Dies geschieht durch die SIM-Anweisung. Dann können wir den Interrupt mit dem EI-Befehl auslösen. Die Endlosschleife liest wiederholt die Adressen 4600h und 4601h und vergleicht sie mit den Kopien an den Adressen 4602h und 4603h. Wenn sie sich unterscheiden, aktualisieren wir zuerst die Kopien. Dann löschen wir das gesamte Display und schreiben die Einstellung des MODE-Schalters darauf, gefolgt vom Namen der gedrückten Taste. Das Programm kennt nicht die Möglichkeit, mehrere Tasten gleichzeitig zu drücken.
Damit das Programm eine bestimmte Funktion hat, können wir die Motoren in der entsprechenden Richtung aktivieren, indem wir die Tasten 2/E, 3/U, 4W und 8/D drücken. Nach dem Loslassen des Knopfes stoppen wir den Motor. Wenn jemand das Programm ändert, um nach mehr gleichzeitigen Tastendrücken zu suchen, muss er sorgfältig darüber nachdenken, wie er darauf reagieren soll. Beispielsweise ist es in Ordnung, sowohl den Azimut- als auch den Elevationsmotor gleichzeitig zu betreiben. Es macht keinen Sinn, die Drehung eines Motors auf beiden Seiten gleichzeitig zu aktivieren. Eine Änderung der Drehrichtung bei laufendem Motor würde wahrscheinlich den Motor beschädigen.
Die Motorschnittstelle ist mit Port C des Schaltkreises 8255A verbunden, d. h. mit Adresse 5802h. Die Motoren werden gesteuert, indem ein Steuerbyte an diesen Port geschrieben wird. Die Bedeutung der einzelnen Bits ist wie folgt:
Adressbits 5802h | Funktion |
0 | Höhenrichtung: 0 = Up; 1 = Down |
1 | Höhenmotor: 0 = Off; 1 = On |
2 | High Speed: 0 = Off; 1 = On |
3 | Azimutrichtung: 0 = West; 1 = East |
4 | Azimut-Motor: 0 = Off; 1 = On |
5 | Nicht benutzt |
6 | Nicht benutzt |
7 | Nicht benutzt |
Ein entsprechendes Programm könnte so aussehen:
jmp Start
.ORG 003Ch
jmp IntRST75
.ORG 0040h
.dseg
nokey .text "and no other key is pressed"
key1 .text "and Key 1 is pressed"
key2 .text "and Key 2/E is pressed"
key3 .text "and Key 3/U is pressed"
key4 .text "and Key 4/W is pressed"
key5 .text "and Key 5 is pressed"
key6 .text "and Key 6 is pressed"
key7 .text "and Key 7 is pressed"
key8 .text "and Key 8/D is pressed"
key9 .text "and Key 9 is pressed"
keyA .text "and Key 0 is pressed"
keyE .text "and Key E is pressed"
keyup .text "and Key Up is pressed"
keydn .text "and Key Down is pressed"
keyprg .text "MODE PRG "
keytch .text "MODE TCH "
keyrun .text "MODE RUN "
.cseg
Start: lxi sp, 4700h ; Set Stack Address
mvi a, 82h ; CW
sta 5803h ; 8255A Write Control Word
xra a ; 0 -> a
sta 5802h ; 0 -> port C: stop motors
mvi a, 0Ch ; LCD Command: Display on, cursor off
call sub_1B70 ; Command -> LCD
mvi a, 00h
sta 4600h ; Initialization RAM
sta 4601h ; Initialization RAM
sta 4602h ; Initialization RAM
sta 4603h ; Initialization RAM
mvi a, 0Bh ; Mask interrupt, 0000 1011, 0 -> bit2
sim ; Set mask
ei ; Enable Interrupt
TestKey: lxi h, 4600h ; Source RAM
mov a, m ; value -> a
lxi h, 4602h
cmp m ; Compare the value with the copy
jnz TestCont ; if value 4600h <> value 4602h, jump
lxi h, 4601h ; Source RAM
mov a, m ; Compare the value with the copy
lxi h, 4603h
cmp m ; Compare the value with the copy
jz TestKey ; if value 4601h = value 4603h, nothing changed, test again
TestCont: lxi h, 4600h ; Source RAM
mov a, m ; value -> a
sta 4602h ; copy
lxi h, 4601h ; Source RAM
mov a, m ; value -> a
sta 4603h ; copy
mvi a, 01h ; LCD Command: Clear Display
call sub_1B70 ; Command -> LCD
lxi h, 4600h ; Mode switch MyCode
mov a, m ; Switch status
cpi 10h ; Is the PRG key?
jnz Test20 ; If not, jump
lxi h, keyprg ; Address of text
mvi b, 09h ; Number of characters
call WrStr ; Text -> LCD
jmp Test01
Test20: lxi h, 4600h ; Mode switch MyCode
mov a, m ; Switch status
cpi 20h ; Is the TCH key?
jnz Test30 ; If not, jump
lxi h, keytch ; Address of text
mvi b, 09h ; Number of characters
call WrStr ; Text -> LCD
jmp Test01
Test30: lxi h, keyrun ; Address of text
mvi b, 09h ; Number of characters
call WrStr ; Text -> LCD
Test01: lxi h, 4601h
mov a, m ; Key MyCode
cpi 01h ; Is the 1 key?
jnz Test02 ; If not, jump
lxi h, key1 ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test02: lxi h, 4601h
mov a, m ; Key MyCode
cpi 02h ; Is the 2/E key?
jnz Test03 ; If not, jump
lxi h, key2 ; Address of text
mvi b, 16h ; Number of characters
call WrStr ; Text -> LCD
mvi a, 18h ; 0001 1000 East = On
sta 5802h
jmp TestKey ; Neverending loop
Test03: lxi h, 4601h
mov a, m ; Key MyCode
cpi 03h ; Is the 3/U key?
jnz Test04 ; If not, jump
lxi h, key3 ; Address of text
mvi b, 16h ; Number of characters
call WrStr ; Text -> LCD
mvi a, 02h ; 0000 0010 Up = On
sta 5802h
jmp TestKey ; Neverending loop
Test04: lxi h, 4601h
mov a, m ; Key MyCode
cpi 04h ; Is the 4/W key?
jnz Test05 ; If not, jump
lxi h, key4 ; Address of text
mvi b, 16h ; Number of characters
call WrStr ; Text -> LCD
mvi a, 10h ; 0001 0000 West = On
sta 5802h
jmp TestKey ; Neverending loop
Test05: lxi h, 4601h
mov a, m ; Key MyCode
cpi 05h ; Is the 5 key?
jnz Test06 ; If not, jump
lxi h, key5 ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test06: lxi h, 4601h
mov a, m ; Key MyCode
cpi 06h ; Is the 6 key?
jnz Test07 ; If not, jump
lxi h, key6 ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test07: lxi h, 4601h
mov a, m ; Key MyCode
cpi 07h ; Is the 7 key?
jnz Test08 ; If not, jump
lxi h, key7 ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test08: lxi h, 4601h
mov a, m ; Key MyCode
cpi 08h ; Is the 8/D key?
jnz Test09 ; If not, jump
lxi h, key8 ; Address of text
mvi b, 16h ; Number of characters
call WrStr ; Text -> LCD
mvi a, 03h ; 0000 0011 Down = On
sta 5802h
jmp TestKey ; Neverending loop
Test09: lxi h, 4601h
mov a, m ; Key MyCode
cpi 09h ; Is the 9 key?
jnz Test0A ; If not, jump
lxi h, key9 ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test0A: lxi h, 4601h
mov a, m ; Key MyCode
cpi 0Ah ; Is the 0 key?
jnz Test0B ; If not, jump
lxi h, keyA ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test0B: lxi h, 4601h
mov a, m ; Key MyCode
cpi 0Bh ; Is the E key?
jnz Test0C ; If not, jump
lxi h, keyE ; Address of text
mvi b, 14h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test0C: lxi h, 4601h
mov a, m ; Key MyCode
cpi 0Ch ; Is the Up key?
jnz Test0D ; If not, jump
lxi h, keyup ; Address of text
mvi b, 15h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
Test0D: lxi h, 4601h
mov a, m ; Key MyCode
cpi 0Dh ; Is the Down key?
jnz TestNoK ; If not, jump
lxi h, keydn ; Address of text
mvi b, 17h ; Number of characters
call WrStr ; Text -> LCD
jmp TestKey ; Neverending loop
TestNoK: lxi h, nokey ; Address of text
mvi b, 1Bh ; Number of characters
call WrStr ; Text -> LCD
mvi a, 00h
sta 5802h ; 0 -> PortC: stop motors
jmp TestKey ; Neverending loop
hlt ; For sure
; Write 1 byte command
sub_1B70: call sub_1B7E ; Wait for LCD ready
sta 4802h ; Write command byte
ret
; Write 1 byte data
sub_1B77: call sub_1B7E ; Wait for LCD ready
sta 4803h ; Write data byte
ret
; Wait for LCD ready
sub_1B7E: push psw
loc_1B7F: lda 4800h ; Read LCD status
ani 80h ; Test bit 7: 0 = ready
jnz loc_1B7F ; if not, repeat
pop psw
ret
; Write string on LCD
WrStr: mov a, m
call sub_1B77 ; Character -> LCD
inx h ; Address of next characters
dcr b ; Decrement counter
jnz WrStr
ret
; Interrupt handling RST7.5
IntRST75: push psw ; Save the contents of the registers to the stack
push b
push d
push h
mvi a, 0F7h
sta 5800h ; Scan Group 3
lda 5801h
ori 0F0h
cpi 0FEh ; Is the PRG key?
jnz TCH_20 ; If not, jump
mvi a, 10h ; The key is PRG, MyCode = 10h
sta 4600h
jmp ScanGr0 ; Go scan group 0
TCH_20: cpi 0FDh ; Is the TCH key?
jnz RUN_30 ; If not, jump
mvi a, 20h ; The key is TCH, MyCode = 20h
sta 4600h
jmp ScanGr0 ; Go scan group 0
RUN_30: cpi 0FBh ; Are the RUN + Up keys?
jnz RUN_31 ; If not, jump
mvi a, 30h ; The key is RUN, MyCode = 30h
sta 4600h
mvi a, 0Ch ; and the key is Up, MyCode = 0Ch
sta 4601h
jmp EndISR ; Finish scanning
RUN_31: cpi 0F7h ; Are the RUN + Down keys?
jnz RUN_32 ; If not, jump
mvi a, 30h ; The key is RUN, MyCode = 30h
sta 4600h
mvi a, 0Dh ; and the key is Up, MyCode = 0Dh
sta 4601h
jmp EndISR ; Finish scanning
RUN_32: mvi a, 30h ; The key must be RUN
sta 4600h
ScanGr0: mvi a, 0FEh ; Mask Group 0
sta 5800h ; Write mask
lda 5801h ; Scan Group 0
ori 0F0h
cpi 0FEh ; Is the 1 key?
jnz Gr0_2 ; If not, jump
mvi a, 01h ; The key is 1, MyCode = 01h
sta 4601h
jmp EndISR ; Finish scanning
Gr0_2: cpi 0FDh ; Is the 2/E key?
jnz Gr0_3 ; If not, jump
mvi a, 02h ; The key is 2/E, MyCode = 02h
sta 4601h
jmp EndISR ; Finish scanning
Gr0_3: cpi 0FBh ; Is the 3/U key?
jnz Gr0_4 ; If not, jump
mvi a, 03h ; The key is 3/U, MyCode = 03h
sta 4601h
jmp EndISR ; Finish scanning
Gr0_4: cpi 0F7h ; Is the 4/W key?
jnz Gr1_1 ; If not, jump
mvi a, 04h ; The key is 4/W, MyCode = 04h
sta 4601h
jmp EndISR ; Finish scanning
Gr1_1: mvi a, 0FDh ; Mask Group 1
sta 5800h ; Write mask
lda 5801h ; Scan Group 1
ori 0F0h
cpi 0FEh ; Is the 5 key?
jnz Gr1_2 ; If not, jump
mvi a, 05h ; The key is 5, MyCode = 05h
sta 4601h
jmp EndISR ; Finish scanning
Gr1_2: cpi 0FDh ; Is the 6 key?
jnz Gr1_3 ; If not, jump
mvi a, 06h ; The key is 6, MyCode = 06h
sta 4601h
jmp EndISR ; Finish scanning
Gr1_3: cpi 0FBh ; Is the 7 key?
jnz Gr1_4 ; If not, jump
mvi a, 07h ; The key is 7, MyCode = 07h
sta 4601h
jmp EndISR ; Finish scanning
Gr1_4: cpi 0F7h ; Is the 8/D key?
jnz Gr2_1 ; If not, jump
mvi a, 08h ; The key is 8/D, MyCode = 08h
sta 4601h
jmp EndISR ; Finish scanning
Gr2_1: mvi a, 0FBh ; Mask Group 2
sta 5800h ; Write mask
lda 5801h ; Scan Group 2
ori 0F0h
cpi 0FEh ; Is the 9 key?
jnz Gr2_2 ; If not, jump
mvi a, 09h ; The key is 9, MyCode = 09h
sta 4601h
jmp EndISR ; Finish scanning
Gr2_2: cpi 0FDh ; Is the 0 key?
jnz Gr2_3 ; If not, jump
mvi a, 0Ah ; The key is 0, MyCode = 0Ah
sta 4601h
jmp EndISR ; Finish scanning
Gr2_3: cpi 0FBh ; Is the E key?
jnz NoKeyIs ; If not, jump
mvi a, 0Bh ; The key is E, MyCode = 0Bh
sta 4601h
jmp EndISR ; Finish scanning
NoKeyIs: mvi a, 00h ; no key is pressed, MyCode = 00h
sta 4601h
; Finish scanning
EndISR: pop h ; Restore the contents of the registers from the stack
pop d
pop b
pop psw
ei ; Enable Interrupt
ret
.END
Die resultierende Binärdatei wird vom Programmierer in den gelöschten EPROM-Speicher geladen und kann getestet werden. Ich glaube, dass die in diesem Programm bereitgestellten Informationen jedem helfen werden, der die ursprüngliche EPS-103-Firmware recherchieren möchte. Den Quelltext des genannten Programms können Sie in der Datei KeyboardEPS103.asm herunterladen.