Kurs: C 64 Extern – Der Weg nach draußen
C 64/VC 20
Extern-Kurs

C 64 extern — Der Weg noch draußen (Teil 3)

Nachdem wir in der letzten Folge die Programmierung der Control-Ports abgeschlossen haben, wenden wir uns heute einer der vielseitigsten Schnittstellen des C 64/VC 20 zu — dem User-Port.

Der User-Port führte neben dem Expansion-Port lange Zeit ein Schattendasein, denn an ihm können keine Programm-Module verwendet werden. Mittlerweile hat der User-Port aber weit aufgeholt. Er wird für Steuerzwecke, zum Anschluß eines Druckers, für die RS232 und auch zum Programmieren von EPROMs mit einem Zusatzgerät verwendet. Sehen wir uns diese interessante Schnittstelle etwas genauer an. Die Anschlußbelegung der User-Ports von C 64 und VC 20 zeigen die Bilder 1 und 2. Beachten Sie bitte, daß die Anschlüsse an der Ober- und Unterseite des User-Ports verschiedene Funktionen haben. Klemmen Sie deshalb dort niemals eine Krokodilklemme oder vergleichbares an! Ich möchte Ihnen nun zuerst zeigen, wie der 8-Bit-Parallelport am User-Port programmiert wird. Dieser Port bietet sehr vielseitige Anwendungsmöglichkeiten, obwohl er einfach zu programmieren ist. Angesprochen wird er über die acht Leitungen PB0 bis PB7 (Pin C bis L).

Über den Parallelport kann man Daten einlesen und Daten ausgeben. Das Praktische an dieser Tatsache ist, daß man die Richtung der Daten für jede der acht Leitungen einzeln bestimmen kann. Warum es aber gerade acht Leitungen gibt, hat einen einfachen Grund: Zur Steuerung des Ports gibt es im Computer zwei verschiedene Speicherstellen. Jeder Leitung am Port ist in jeder dieser Speicherstellen genau ein Bit zugeordnet. Daher also acht Leitungen, gleich acht Bit, gleich ein Byte.

Welche Bedeutungen haben nun diese beiden Speicherzellen? Die erste nennt sich »DDR«. Das heißt »Data Direction Register« (Datenrichtungsregister). Hier wird, wie der Name schon sagt, die Datenrichtung festgelegt. Aber wie? Dem Bit X im DDR ist die Datenleitung PBX zugeordnet. Ist zum Beispiel Bit 2 in diesem Register auf 1, dann ist die Leitung PB2 als Ausgang deklariert. Eine 0 macht die entsprechende Leitung zum Eingang. So einfach ist das!

Die zweite bereits genannte Speicherstelle enthält die eigentlichen Daten. Man bezeichnet sie als Portregister.

Nehmen wir einmal an, wir hätten in das Datenrichtungsregister die Zahl 255 eingeschrieben, also alle Leitungen als Ausgänge programmiert. Eine 255 im Portregister legt dann High-Pegel auf alle acht Datenleitungen. Eine 0 im Portregister bewirkt GND auf allen Datenleitungen. Man kann also wie im Datenrichtungsregister bitweise den Spannungszustand am Ausgang bestimmen (l = high, 0 = low). Hierbei ist Bit 0 wieder PB0 zugeordnet. Die Spannungspegel, die wir am Port erhalten, können wir dann »extern« verarbeiten, doch davon später.

Im zweiten Beispiel benutzen wir den Parallelport als Eingang. Nehmen wir an, wir hätten in das Datenrichtungsregister eine 0 eingeschoben, also alle Datenleitungen als Eingänge definiert. Jetzt müssen wir »externe« Daten an den Port anlegen. Das geschieht durch Verbinden der Datenleitungen entweder mit + 5 V oder GND der Computerversorgungsspannung. Dabei entspricht einer »0« GND und eine »1« + 5V. Eine »1« entsteht auch, wenn eine Leitung nicht angeschlossen, also weder mit + 5 V noch mit GND verbunden wird. Das spart oft viel Schaltungsaufwand. Die an den Port angelegte Bitkombination kann jederzeit durch Abfragen des Portregisters ausgelesen werden. Der neue Zustand der Datenleitungen wird, wenn sich etwas geändert hat, jeweils sofort und automatisch in das Portregister übernommen.

Die beiden Funktionen Eingänge/Ausgänge dürfen, wie schon gesagt, beliebig gemischt werden. So ist beispielsweise möglich, die Leitungen 2, 5 und 7 als Ausgänge und alle restlichen Leitungen als Eingänge zu definieren. Dazu müßte man im Datenrichtungsregister die Zahl 164 ablegen (164 = Bits 2, 5 und 7 gesetzt). Die Information über die Spannungszustände an den Ausgängen müßte in die Bits 2, 5 und 7 des Portregisters gePOKEt und die Information über die Eingänge aus den Bits 0, 1, 3, 4 und 6 des Portregisters ausgelesen werden.

Nach soviel grauer Theorie wollen wir endlich wieder etwas programmieren. Bevor es losgeht, müssen Sie noch wissen, wie die Adressen der eben besprochenen Speicherstellen lauten. Sie sind in Tabelle 1 aufgelistet. Jetzt haben wir alles nötige Rüstzeug, um voll in eine sinnvolle Anwendung des Computers einzusteigen: Programmieren wir eine Alarmanlage!

DATENRICHTUNGS-REGISTER PORTREGISTER
VC 20 37138 37136
C 64 56579 56577
Tabelle 1. Zusammenstellung der User-Port-Register

Alarmanlage per User-Port

Tippen Sie Listing 1 ab und starten Sie das Programm mit RUN. Auf dem Bildschirm erscheint der Kontaktplan des Parallelports. Hoffentlich haben Sie beim Einkauf für die letzte Folge an den Stecker für den User-Port gedacht, den brauchen wir nämlich jetzt.

Bringen Sie an einem der vier Eckkontakte (= GND, siehe Bild 1) des User-Port-Steckers einen Draht an, und stecken Sie den Stecker in den User-Port. Zum Anbringen des Drahtes ist Löten wohl das Beste. Keinesfalls dürfen Sie einen anderen Anschluß versehentlich berühren, beziehungsweise mit GND in Verbindung bringen.

PIN BELEGUNG PIN BELEGUNG
1 GND A GND
2 +5V, max. 100 mA B FLAG2
3 RESET C PB0
4 CNT1 D PB1
5 SP 1 E PB2
6 CNT2 F PB3
7 SP 2 H PB4
8 PC2 J PB5
9 SER. ATN IN K PB6
10 9V AC, max. 100 mA L PB7
11 9V AC, max. 100mA M PA2
12 GND N GND
Bild 1. Anschlußbelegung des C 64 User-Ports. (Bei Aufsicht auf die Computerrückseite)

Nehmen Sie sich nun das andere Ende des Drahtes zur Hand, und berühren Sie damit eine der Datenleitungen PB1 bis PB7. Bitte nicht die Datenleitung PB0, da diese vom Programm als Ausgang (Alarmanzeiger) benutzt wird (was wir mit diesem machen können, sehen wir in der nächsten Folge). Welche Pins die richtigen sind, können Sie Bild 1 und 2 entnehmen.

PIN BELEGUNG PIN BELEGUNG
1 GND A GND
2 +5V, max. 100 mA B CB1
3 RESET C PB0
4 JOY 0 D PB1
5 JOY 1 E PB2
6 JOY 2 F PB3
7 LIGHT PEN H PB4
8 CASSETTE SWITCH J PB5
9 SERIAL ATN IN K PB6
10 9V AC, max. 100 mA L PB7
11 9V AC, max. 100 mA M CB2
12 GND N GND
Bild 2. Anschlußbelegung des VC 20 User-Ports. (Bei Aufsicht auf die Computerrückseite)

Beim Berühren erklingt ein Alarmton, der Bildschirmrahmen ändert die Farbe, und der Alarmanzeiger (PB0) geht auf high (+5 V). Zusätzlich wird auf dem Bildschirm angezeigt, welche Kontakte den Alarm ausgelöst haben. Wenn Sie keine der Datenleitung mehr mit dem Draht berühren, die Eingänge also alle High-Signal erhalten, werden alle Alarmsignale sofort gelöscht.

Werfen wir einen Blick auf das Listing. Nach der Initialisierung der Variablen, der Portregister, des SID-Chips und des Bildschirms wird in Zeile 390 das Portregister (Variable R) so lange ausgelesen, bis ein anderer Wert als 254 auftaucht. Warum 254? 254 ist die Summe der Wertigkeiten der Bits 1 bis 7, also aller Bits des Portregisters ohne den Alarmanzeiger. Das ist der Ruhezustand der Alarmanzeige; alle Kontakte sind geöffnet ( = High-Pegel).

Wird ein Alarm ausgelöst, dann werden ab Zeile 430 sämtliche Alarmanzeiger eingeschaltet. Ab Zeile 470 wird ein neuer Kontaktplan ausgegeben. Dabei wird jeder Kontakt auf Alarm überprüft und das Ergebnis angezeigt.

Anschließend wartet der Computer auf das Alarmende. Wenn noch Alarm besteht, wird wieder ein neuer Kontaktplan ausgegeben, weil sich am Kontaktzustand etwas geändert haben kann. Andernfalls werden die Alarmanzeiger ausgeschaltet und es wird zur Bildschirminitialisierung zurückgesprungen.

Wer sich das Programm genau ansieht, wird schnell feststellen, daß es so, wie es hier abgedruckt ist, zum realen Einsatz als Alarmanlage weniger geeignet ist. Dazu hat es verschiedene Schwächen. Zum einen wird nicht mit Sicherheit jeder Alarm erkannt: Wenn der Alarmimpuls sehr kurz ist, kann es passieren, daß der C 64 gerade etwas anderes tut, als das Portregister auszulesen, zum Beispiel den Rücksprung nach 390 ausführen. Außerdem ist der eigentlich alarmauslösende Zustand am Portregister nicht der, der ausgewertet wird, weil der auszuwertende Zustand erst nach dem Alarmauslösen in Zeile 420 ermittelt wird. In der Zwischenzeit kann sich schon etwas verändert haben. Das genannte trifft aber nur auf sehr kurze Impulse zu.

Zum anderen ist die Auswertung des Alarmes viel zu einfach gehalten, eben nur als Beispiel. Wenn hier ein Alarm von einer Sekunde auftritt, wird auch nur eine Sekunde lang Alarm gegeben, was natürlich viel zu wenig ist.

Codeschloß

Kommen wir zu einem weiteren Programmbeispiel, dem Codeschloß in Listing 2. Wir haben es wieder mit Raumsicherung zu tun. Wieder wird die Datenleitung PB0 als Ausgang und die restlichen Datenleitungen als Eingänge benutzt.

Was leistet das Programm? Sie müssen durch Verbinden der Datenleitungen PB2 bis PB7 einen sechsstelligen Code eingeben. Wenn Sie keinen Fehler gemacht haben, wird die Datenleitung PB0 auf high gelegt, also beispielsweise eine Tür geöffnet oder eine geheime Anlage eingeschaltet. Wie Sie solche Dinge ansteuern können, erfahren Sie im nächsten Teil dieses Kurses. Über die Leitung PB1 wird das Codeschloß zurückgesetzt (sowohl nach dem Auslösen des Schlosses als auch nach einer Fehlereingabe). Jede Berührung an den Eingängen wird durch einen Signalton quittiert.

In den Zeilen 250/260 werden zwei Variablen deklariert, deren Bedeutung ich kurz erläutern möchte. CL enthält die Länge des einzugebenden Codes, CI$ den Code selbst. Den Inhalt dieser beiden Variablen können Sie nach Belieben verändern. Der von mir gewählte Code ist bewußt sehr primitiv.

In C2$ wird der Code aufgebaut, den Sie durch Berühren der »externen« Kontakte eingeben. Der große Vorteil hierbei ist, daß die Eingabeeinheit für den Code an einer anderen Stelle (zum Beispiel im Nebenraum) als der Computer sein kann. Man wird also von der Computertastatur unabhängig. Mit einem langen Code wird ein Knacken theoretisch unmöglich. Da sich das Programm durch REM-Anweisungen selbst dokumentiert, bleibt nur noch zu sagen, daß es der Einfachheit halber bei jedem »RESET« an Kontakt PB1 einfach neu mit RUN gestartet wird.

Auch bei diesem Programm ist nur eine Minimallösung angegeben. Man kann es um viele Raffinessen erweitern, so daß zum Beispiel ein Einbruchsversuch als solcher gedeutet wird und so weiter.

Nachdem wir nun wissen was sich am User-Port abspielt, wollen wir noch einmal einen Schritt zurückgehen. Im ersten Teil dieses Kurses sind ein paar Fragen offen geblieben, die ich jetzt beantworten möchte.

Da war als erstes die Sache mit der Umschaltung des Computers auf Joystickeingabe. Vielleicht haben Sie schon eine Ähnlichkeit zwischen Joystick- und Parallelport-Programmierung entdeckt. Bei beiden mußte etwas umgeschaltet werden. Dann gab es zwei mögliche Zustände: 0 oder 1! Die Umschaltung des Computers auf Joystickeingabe ist nichts anderes als die Programmierung des zugehörigen Datenrichtungsregisters. Bitte erinnern Sie sich: Wir haben bei der Umschaltung die zugehörigen Bits gelöscht, also die Datenleitungen der Control-Ports zu Eingängen gemacht. Wer darüber nachdenkt, wird schnell zu der Frage kommen, was denn passiert, wenn wir in die DDRs einfach Einsen hineinschreiben. Die Antwort ist trivial: Die Joystickleitungen werden zu Ausgängen! Doch darum wollen wir uns erst im dritten Teil dieses Kurses kümmern. Die Zusammenstellung aller Adressen, die hierfür interessant sind, zeigt Tabelle 2.

DATENRICHTUNGS-REGISTER PORTREGISTER
C 64, PORT 1 56323 56321
C 64, PORT 2 56322 56320
VC 20 37139 / 37154 37137 / 37152
Tabelle 2. Zusammenstellung der Control-Port-Register

Als nächstes interessiert Sie wahrscheinlich, warum eigentlich Paddles, Joystick, Lichtgriffel und Tastatur einander behindern. Das kommt daher, daß alle diese Eingabeeinheiten dieselben Datenleitungen benutzen. Aus diesem Grund sind auch die Umschaltungen notwendig.

Warum aber benutzt die Tastatur Leitungen am Control-Port? Eine Computertastatur ist durch eine Matrix aus Zeilen und Spalten mit dem Computer verbunden. An jedem Kreuzungspunkt sitzt eine Taste, die, wenn sie gedrückt wird, die beiden Leitungen des Kreuzungspunktes miteinander verbindet. Die Routine des Betriebssystems, welche die Tastatur abfragt, legt nun an eine Zeile ein Signal an und überprüft, in welcher Spalte dieses Signal auftritt. Daraus läßt sich ableiten, welche Taste gedrückt ist. Wird kein Signal entdeckt, so ist in dieser Zeile keine Taste gedrückt, und das Signal wird an die nächste Zeile angelegt. Aus diesem Verfahren erklärt sich, warum einige Tasten Priorität gegenüber anderen haben. Das können Sie feststellen, indem Sie mehrmals zwei Tasten gleichzeitig drücken. Es wird immer dieselbe Taste vom Computer registriert werden.

Diese Zeilen- und Spaltenmatrix liegt auf denselben Leitungen wie der Joystick, weil auch hier »externe« Signale gegeben und Informationen gelesen werden müssen, wozu unser Computer eben nur eine bestimmte Anzahl von Bausteinen hat. Deshalb funktioniert die Tastatur nach dem POKEn in die Control-Port-DDRs meist nicht mehr, weil sie nicht mehr ordnungsgemäß decodiert wird. Die Werte, die in bestimmte Speicherzellen immer wieder hineingeschrieben werden (siehe Folge 1) stammen auch aus der Tastaturdecodierungs-Routine.

Die Störung der Tastatur kommt nun daher, daß es dem Computer völlig gleichgültig ist, ob Sie den Joystickhebel bewegen oder auf die Tasten hämmern. Er prüft artig seine Spalten nach und kümmert sich nicht darum, woher die festgestellte Verbindung denn nun kam. Die Störung durch den Lichtgriffel hat dieselbe Ursache.

Jetzt müssen wir nur noch einen Rückstand aus der letzten Folge aufklären. Dabei handelt es sich um die Feuerknöpfe der Paddles. Ich kann Ihnen erst jetzt zeigen wie sie abgefragt werden, weil wir auch hier die Kenntnisse über die Programmierung des Parallelports benötigen. Es funktioniert nämlich schon wieder genauso: Man setze im zugehörigen DDR die entsprechenden Bits auf Null (Leitung auf Eingang schalten) und frage dann die entsprechenden Bits im zugehörigen Portregister ab. Natürlich zeigt auch hier wieder eine Null im Portregister an, daß der Feuerknopf am Paddle gedrückt wurde. In Tabelle 3 sind die nötigen Informationen für Port 1 des C 64, in Tabelle 4 die für den Port 2 und in Tabelle 5 die für den VC 20 zusammengefaßt. Dabei sind die Paddles gemäß der Position ihres Verbindungskabels am Control-Port mit links und rechts bezeichnet. Das rechte Paddle ist also an POT X, das linke an POT Y angeschlossen. Da die Feuerknöpfe der Paddles dieselben Leitungen wie der Joystick benutzen, gilt hier ebenfalls das oben Beschriebene über die gleichzeitige Benutzung von Paddles und Tastatur.

ANSCHLUSS PIN BIT DATENRICHTUNGS-REGISTER PORTREGISTER
RECHTS JOY 3 4 3 56323 56321
LINKS JOY 2 3 2 56323 56321
Tabelle 3. Daten zur Abfrage der Paddle-Knöpfe beim Port 1 des C 64
ANSCHLUSS PIN BIT DATENRICHTUNGS-REGISTER PORTREGISTER
RECHTS JOY 3 4 3 56322 56320
LINKS JOY 2 3 2 56322 56320
Tabelle 4. Daten zur Abfrage der Paddle-Knöpfe beim Port 2 des C 64
ANSCHLUSS PIN BIT DATENRICHTUNGS-REGISTER PORTREGISTER
RECHTS JOY 3 4 7 37154 37152
LINKS JOY 2 3 4 37139 37137
Tabelle 5. Daten zur Abfrage der Paddle-Knöpfe beim VC 20

Damit wollen wir es für heute bewenden lassen. Das nächste mal sehen wir dann, wie versprochen, wo sich den Control-Ports Signale entnehmen lassen. Außerdem wollen wir uns mit Anschlußmöglichkeiten verschiedener Adapter an den User-Port beschäftigen und unter anderem einen 220 Volt-Adapter für unseren Computer bauen!

(Tobias Nicol/aw)
100 rem *******************************
110 rem *                             *
120 rem *    a l a r m a n l a g e    *
130 rem *    ---------------------    *
140 rem *                             *
150 rem *       by tobias nicol       *
160 rem *                             *
170 rem *     neuwiesenstrasse 20     *
180 rem *                             *
190 rem *      6000 frankfurt 71      *
200 rem *                             *
210 rem *******************************
220  
230 rem ******* initialisierung *******
240 r = 56577 : poke 56579,1 : poke r,0
250  
260 rem ***** sid-chip einstellen *****
270 t = 54296 : si = 54272
280 poke si+ 7,207 : poke si+ 8,200
290 poke si+13,240 : poke si+11,17
300  
310 rem ***** bildschirm aufbauen *****
320 print "{clr}{down}{down}{rght}{rght}{rght}{rght}{rght}alarmanlage"
330 print "{rght}{rght}{rght}{rght}{rght}==========={down}{down}{down}"
340 for a = 1 to 7
350 print"kontakt"a": o. k.{down}"
360 next a
370  
380 rem *********** alarm? ************
390 if ((peek(r))and254) = 254 then 390
400  
410 rem *********** alarm! ************
420 ir = peek (r)
430 poke 53280,2
440 poke r , peek ( r ) or 1
450 poke t,15
460  
470 rem **** kontaktplan ausgeben  ****
480 print "{home}{down}{down}{down}{down}{down}{down}"
490 for a = 1 to 7
500 if (ir and (2^a)) = 0 then 530
510 print "{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}o. k. {down}"
520 goto 540
530 print "{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}alarm!{down}"
540 next a
550  
560 rem ****** immer noch alarm? ******
570 ir = peek ( r )
580 if ( ir and 254 ) <> 254 then 470
590  
600 rem ** alarmanzeiger ausschalten **
610 poke 53280,254
620 poke r , peek ( r ) and 254
630 poke t,0
640  
650 rem ********* ruecksprung *********
660 goto 310
670  
680  
690  
700 rem *******************************
710 rem *** aenderungen fuer vc-20  ***
720 rem *******************************
730 rem
740 rem loeschen sie  : zeilen 270-290.
750 rem
760 rem geben sie ein :
770 rem
780 rem 240 r=37136:poke37138,1:poker,0
790 rem 270 t=36878 : poke36875,200
800 rem 430 poke 36879,26
810 rem 610 poke 36879,27
Listing 1. Die User-Port-Alarmanlage. Beachten Sie bitte die Eingabehinweise auf Seite 54.
100 rem *******************************
110 rem *                             *
120 rem *    c o d e s c h l o s s    *
130 rem *    ---------------------    *
140 rem *                             *
150 rem *       by tobias nicol       *
160 rem *                             *
170 rem *     neuwiesenstrasse 20     *
180 rem *                             *
190 rem *      6000 frankfurt 71      *
200 rem *                             *
210 rem *******************************
220  
230 rem ******* initialisierung *******
240 r = 56577 : poke 56579,1 : poke r,0
250 t = 54296 : i = 1 : cl = 6
260 c1$ = "123456" : c2$ = ""
270  
280 rem ***** sid-chip einstellen *****
290 si = 54272
300 poke si+ 7,207 : poke si+ 8,200
310 poke si+13,240 : poke si+11,17
320  
330 rem ***** bildschirm aufbauen *****
340 print "{clr}{down}{rght}{rght}{rght}{rght}{rght}{blk}codeschloss"
350 print "{rght}{rght}{rght}{rght}{rght}-----------{cyn}"
360 print "{down}{down}geben sie bitte den{down}"
370 print "code ein. jeder kon-{down}"
380 print "takt wird mit einem{down}"
390 print "ton bestaetigt."
400 print "{down}{down}(reset: kontakt 2)"
410  
420 rem ***** kontakt betaetigt?  *****
430 pr = (( peek (r) and 254 ))
440 if ( pr and 254 ) = 254 then 420
450  
460 rem *** kontaktnummer errechnen ***
470 x = log ( 254 - pr ) / log (2) - 1
480  
490 rem ***** werte kontrollieren *****
500 if ( x < 0 ) or ( x > 6 ) then 420
510 if x <> int (x) then 420
520  
530 rem *********** reset?  ***********
540 if x = 0 then run
550  
560 rem * einzugebenden code aufbauen *
570 c2$ = c2$ + right$ ( str$ (x) , 1 )
580  
590 rem ***** signalton ausgeben  *****
600 poke t,15
610 for a = 1 to 30 : next a
620 poke t,0
630  
640 rem **** sind schon cl zahlen  ****
650 rem ****  eingegeben worden?   ****
660 i = i + 1
670 if i = cl + 1 then 720
680  
690 rem ********* ruecksprung *********
700 goto 420
710  
720 rem * eingegebener code richtig?  *
730 if c1$ = c2$ then 790
740  
750 rem *** code ist nicht richtig! ***
760 print "{down}{down}{grn}fehler!!!{cyn}"
770 for a = 1 to 2000 : next a : run
780  
790 rem ****** code ist richtig! ******
800 print "{down}{down}{grn}richtig!!!{cyn}"
810 print "{down}bitte mit kontakt 2"
820 print "{down}loeschen!"
830  
840 rem *** user-port-signal setzen ***
850 poke r , ( peek (r) ) or 1
860  
870 rem **** auf den reset warten  ****
880 if (( peek (r)) and 2) = 2 then 870
890 run
900  
910  
920  
930  rem ******************************
940  rem *** aenderungen fuer vc-20 ***
950  rem ******************************
960  rem
970  rem loeschen sie  : zeilen 290-310
980  rem
990  rem geben sie ein :
1000 rem
1010 rem 240 r=37136:poke 37138,1
1020 rem 250 poke r,0:t=36878:i=1:cl=6
1030 rem 290 poke 36876,220
Listing 2. Das Codeschloß
Kurs: C 64 Extern – Der Weg nach draußen
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →