# Bedienungsanleitung
Version 7.1

Erstellt ab 6. Juni 2012
von Dietmar Harlos
letztes Update: 16. August 2026

## Vorwort

Die vorliegende Bedienungsanleitung soll den Umgang mit der Open-Macro und der neuen Open-Maxi erleichtern. Der größte Teil beschäftigt sich mit der Programmierung im neuen OCBASIC-Dialekt. Zunächst beginnen wir aber mit der Beschreibung, was die OM eigentlich ist und wie sie entstanden ist. Da die Open-Macro und Open-Maxi maßgeblich zur C-Control Version 1.1 kompatibel sind, kann auch die Bedienungsanleitung zur C-Control zur Hand genommen werden.
Die Dokumentation besteht aus einer einzigen HTML-Seite, die dementsprechend unkompliziert ausgedruckt oder in ein anderes Dateiformat (wie DOC, PDF, PS, HLP, etc.) konvertiert werden kann. Es läßt sich auch sehr einfach nach einem Stichwort mittels Ctrl+F, bzw. Strg+F suchen. Um schneller in die einzelnen Hauptkapitel zu gelangen, wird in Frame-fähigen Internetbrowsern am linken Rand ein Menü angezeigt. Jeder Internetbrowser formatiert diese Dokumentation etwas anders. Die beste Formatierung wird mit dem Internet Explorer erzielt.
Diese Bedienungsanleitung ist nicht perfekt. Wer möchte, kann die Anleitung um zusätzliche Kapitel ergänzen oder die vorhandenen Erklärungen erweitern. Dann aber nicht diese HTML-Datei editieren, sondern mir den Text in einer E-Mail zusenden.

## Das Open-Control-Projekt

Das Open-Control-Projekt wurde von Dietmar Harlos ins Leben gerufen, um eine Alternative zur C-Control/Micro und einen würdigen Nachfolger für die C-Control I Version 1.1 M-Unit anzubieten. Das Ziel dieses Projektes ist es, unkompliziert zu programmierende Controller zu entwickeln, die weitgehend kompatibel zur C-Control/Micro und zur C-Control I Version 1.1 M-Unit sind, aber gleichzeitig einen deutlich größeren Funktionsumfang besitzen. Außerdem wurde großen Wert auf Fehlerfreiheit und gute Dokumentation gelegt. Als Ergebnis ist die Open-Micro entstanden. Und so ganz nebenbei entstand die Open-Mini gleich mit dazu. Diese beiden Controller unterscheiden sich nur von der Anzahl der zur Verfügung stehenden Ports. Die Open-Midi ist die große Schwester der Open-Mini. Denn sie ist maßgeblich kompatibel zu den bisherigen OM-Controllern, bietet jedoch deutlich mehr Speicher. Die Open-Macro unterstützt 16 Bit Handling und die Open-Maxi ist - soweit sinnvoll und möglich - in Hard- und Software abwärtskompatibel zur weitverbreiteten C-Control I Version 1.1 M-Unit, unterstützt aber gleichzeitig viele Features der bisherigen OM-Mikrocontroller.
Als Basis für die Open-Micro wurde wie auf der Original-Micro ein 68HC908QT4 von Freescale (früher Motorola) im PDIP-8-Gehäuse verwendet. Die Open-Mini basiert auf einem 68HC908QY4-Controller in PDIP-16. Somit stehen auf der Open-Micro 6 Ports und auf der Open-Mini 14 Ports zur Verfügung, die mehrfach belegt sind. Die Open-Midi und Open-Macro basieren auf dem 68HC908QB8, der die gleiche Gehäuseform und Pinbelegung wie die Open-Mini hat. Die Open-Maxi basiert auf der Open-Control M-Unit-Hardware von CCTools, die pinkompatibel zur C-Control I Version 1.1 M-Unit ist. Sie ist mit dem HCS08-Mikrocontroller MC9S08AW60 bestückt. Auf der Open-Maxi stehen deshalb über 24 I/O-Ports, 8 AD-Ports, 2 Frequenzmeßeingänge, 2 PWM-Analogausgänge, BEEP, TEST, eine herausgeführte Referenzspannung für den AD-Wandler und andere Features gleichzeitig zur Verfügung. Die Open-Maxi bietet alle Features der C-Control I Version 1.1 M-Unit und darüber hinaus noch sehr viel mehr Ressourcen.
Das "Open" im Namen symbolisiert, daß diese Controller nicht verschlossen sind wie die Original-Micro, sondern im Gegenteil offen für einen einfachen Einstieg in die Welt der 68HC08er. Es sind alle Controller-Ressourcen nutzbar und es können unter anderem eigene Assembler-Routinen entwickelt und sehr komfortabel in das BASIC-Programm eingebunden werden. Es ist sogar möglich, ein Betriebssystem-Update durchzuführen. Damit können auch ältere OMs immer auf den neuesten Stand gehalten werden, um neue Features nutzen zu können.

## Die OM-Mikrocontroller

Das Bild zeigt links die Open-Micro, rechts die Open-Mini und in der Mitte die neue Open-Control M-Unit mit dem Open-Maxi-Betriebssystem. Die Open-Midi und Open-Macro haben die gleiche Gehäuseform und Pinbelegung wie die Open-Mini.
Die Betriebssysteme der OM-Controller wurden auf geringe Größe bei maximalem Funktionsumfang optimiert, um mehr Platz für Anwenderprogramme zu schaffen. Auf den kleinen OM-Controllern Open-Micro, Open-Mini, Open-Midi und Open-Macro stehen bis zu 6462 Byte zur Programmspeicherung zur Verfügung. Aber die Open-Maxi bietet mit 58782 Byte den größten Programmspeicher. Darüber hinaus gibt es die Möglichkeit, den speziell an die OM-Controller angepaßten Open-Control/BASIC-Compiler zu verwenden, der durch Verwendung neuer Tokenbefehle die Programmgröße um typisch 20% reduziert. Der große Vorteil von OCBASIC ist die hohe Kompatiblität zu CCBASIC. Der auf der Open-Micro und Open-Mini zur Variablenspeicherung zur Verfügung stehende RAM-Speicher ist 64 Byte groß, wobei einige Betriebssystemfunktionen abgeschaltet werden können und so der Speicher auf mehr als 80 Byte ausgedehnt werden kann. Die Open-Midi bietet Anwendungen sogar über 170 Byte Variablenspeicher. Und die Open-Maxi 512 Byte - mit PEEK und POKE sogar über 1800 Byte.
Die Taktung wird bei den kleinen OM-Controllern standardmäßig intern durchgeführt, wodurch keine Pins am Controller belegt werden. Mit externer Taktung sind bis zu 8 MHz Bustakt möglich. Den höchsten Takt bietet die Open-Maxi mit 20 MHz Bustakt. Die OM-Controller sind deshalb 16 bis über 100 mal schneller als die Original-C-Control!
Interessant an den OM-Controllern ist vor allen Dingen, daß ein Anfänger seine ersten Programme in einfachstem BASIC schreiben kann, um sich dann nach und nach tiefer in die 68HC08-Materie einzuarbeiten. Man darf sich von den geringen Ausmaßen nicht täuschen lassen: Es handelt sich um vollwertige Mikrocontroller und durch die Möglichkeit der Programmierung in Assembler steht der gesamte Controller offen.

### Die Vorteile der Open-Macro

- Sorgsam erstelltes und ausführlich getestetes Betriebssystem.
- Komfortables 16-Bit-Handling. Dadurch können Word-Variablen verwendet werden. Die C-Control/Micro bietet nur Byte.
- Die Open-Macro ist in hohem Maße softwarekompatibel zur Original-C-Control (Version 1.1), weshalb sie genauso einfach zu programmieren ist und von vielen Programmiersprachen unterstützt wird.
- Mehr als 140 Byte freier RAM-Speicher. Das heißt, es sind bis zu 140 Byte- oder 70 Word-Variablen nutzbar. Auf der C-Control/Micro sind es nur 24 Byte.
- Es steht 5438 Byte Programmspeicher zur Verfügung. Das ist das 2,7-fache der C-Control/Micro. Darüber hinaus läßt sich durch den optimierten OCBASIC-Compiler ein Programm um typisch 20% verkleinern.
- 14 Digitalports, 10 AD-Ports mit bis zu 10 Bit Auflösung und neue Hardwaremodule.
- Die Gehäuseform DIP-16 bietet den optimalen Kompromiß zwischen geringer Größe und leichter Handhabung.
- Bis zu 8 MHz Bustakt. Dadurch ist die Open-Macro in Benchmark-Tests deutlich schneller als die C-Control I UNIT M 2.0.
- Zwei Serielle Schnittstellen: Die Semi-Dual-Wire-Schnittstelle an PORT[1] arbeitet so wie bei den bisherigen OM-Controllern und es gibt eine hardwaremäßig implementierte 2. Serielle Schnittstelle (ESCI), die mit einem 8 Byte großen Empfangsbuffer arbeitet. Über das ESCI kann der Programmdownload mit bis zu 38400 Baud durchgeführt werden.
- Zur Erhöhung des Funktionsumfangs existieren viele Softwaremodule, die bei Bedarf in eigene Programme integriert werden können. Es gibt unter anderem Softwaremodule für den I²C-Bus, für ein I²C-LCD, für Pulsweitenmodulation (PWM), für die DCF77-Signalauswertung, für 64 Extended Ports, für Modellbau-Servos, für Grundrechenarten in 32 Bit, für IEEE-Fließkommazahlen ("Gleitkommazahlen"), zur Reproduzierung von Infrarot-Signalen und für 1-Wire Digitalthermometer.
- Fehlende Funktionalität läßt sich durch das offene System meist leicht nachrüsten.
- Die Open-Macro kann vom Anwender bei Bedarf auf Open-Midi umgeflasht werden.
- LOOKTAB arbeitet optional im Byteformat, dadurch belegen Tabellen nur halb soviel Programmspeicher.
- Leicht zu erlernende 6808-Assemblersprache.
- Durch den in OCBASIC integrierten 6808-Assembler ist die Assemblerprogrammierung auf den OM-Controllern so komfortabel, wie auf keinem anderen C-Control-kompatiblen Controllersystem. Assemblerroutinen belegen nicht mehr 256 Byte Speicher, sondern nur noch soviel wie nötig. Außerdem sind mehrere Assemblermodule gleichzeitig nutzbar.
- Höhere Ausführungsgeschwindigkeit durch neue Tokenbefehle in Verbindung mit OCBASIC.
- Keine Störungen ("glitches") mehr an den Digitalports, da das Betriebssystem nicht wie die neue C-Control I die Richtungsregister vor den Datenregistern setzt.
- Kein Überschreiben von Systemdaten durch Überlauf des Rechen- oder GOSUB-Stacks wie bei der neuen C-Control I möglich.
- Die C-Control/Micro unterstützt viele BASIC-Befehle nicht mehr, die auf der OM wieder zur Verfügung stehen. Es handelt sich um PULSE, INPUT, NAND, NOR, ABS, SQR, MIN, MAX, SGN, RANDOMIZE, INTERRUPT und RETURN INTERRUPT.
- Einsparung eines Pins durch Semi-Dual-Wire-RS232. Diese RS232 verhält sich wie eine normale Serielle Schnittstelle mit getrenntem RXD und TXD.
- FREQ liegt nicht mehr an Port[4] wie bei der C-Control/Micro sondern an Port[3]. Dadurch bleibt Port[4] voll nutzbar.
- Das Betriebssystem läßt sich konfigurieren (durch PrintHex, RunOnErr, End2Host und vieles mehr).
- Fehlerhandling ist in BASIC möglich.
- Fehlerfreie Unterstützung der BASIC-Interruptroutine.
- Unterprogramme können bis zu 8 Ebenen tief verschachtelt werden.
- Die Ports lassen sich auch im Byteformat ansprechen.
- Auf die Variablen im RAM kann per Pointer zugegriffen werden.
- Dateioperationen (OPEN# FOR, PRINT#, INPUT#, etc.) werden voll unterstützt und sind im Betriebssystem bereits integriert. Optional läßt sich im Byte-Format speichern. Das Betriebssystem ist während des Schreibens in den User-Flash geschützt.
- User-Assemblerroutinen lassen sich in jeden Interrupt und selbst in den Interpreter einbinden.
- In BASIC kann auch ohne Assembler auf den gesamten Speicher zugegriffen werden.
- Das Carry-Flag der letzten Berechnung wird zurückgeliefert.
- Bei kritischen Fehlern in der Software wird in den ROM-Monitor MON08 gesprungen. Der MON08 läßt sich direkt nutzen.
- Der Controller 68HC908QB8, auf dem die Open-Macro basiert, läßt sich ohne Einschränkungen nutzen.
- Betriebssystemupdate ist möglich.
- Variablen können mittels Dateifunktionen dauerhaft im User-Flash gespeichert werden.
- In Assemblerprogrammen sind diverse Firmwareroutinen nutzbar.
- Controller startet nicht mehr automatisch nach Programmdownload, sondern kann über RS232 gestartet werden.
- Controller kann aus BASIC heraus in den Programmiermodus wechseln, unabhängig von der Stellung des HOST-Schalters.
- Der interne Oszillator der bei CCTools erhältlichen Controller wurde bereits auf typisch 1% genau getrimmt. Die C-Control/Micro weist dagegen einen Fehler von bis zu 25% auf.
- Viele weitere Verbesserungen wie optimierter Aufruf bei SYS, besseres RAND und viele neue interne Variablen.

### Die Vorteile der Open-Maxi

- Sorgsam erstelltes und ausführlich getestetes Betriebssystem.
- Basiert auf der neuesten HCS08-Technologie von Freescale und der verwendete MC9S08AW60-Controller gehört zu den leistungsstärksten HCS08-Mikrocontrollern.
- Komfortables 16-Bit-Handling. Dadurch können unter anderem vorzeichenbehaftete Word-Variablen verwendet werden.
- Die Open-Maxi ist fast vollständig softwarekompatibel zur Original-C-Control (Version 1.1), weshalb sie genauso einfach zu programmieren ist und von vielen Programmiersprachen unterstützt wird.
- Durch bis zu 20 MHz Bustakt ist die Open-Maxi über 100-mal so schnell wie die Original-C-Control, 2,8-mal so schnell wie die C-Control I UNIT M 2.0 und 27% schneller als die C-Control Pro Mega 128. Sie ist damit die bisher schnellste C-Control-1-Variante!
- Mehr als 1800 Byte freier RAM-Speicher. Mit den Standardfunktionen sind 256 Byte- oder 256 Word-Variablen nutzbar. Auf der neuen C-Control I sind es nur 140 Byte- oder 70 Word-Variablen.
- Es steht 58782 Byte Programmspeicher zur Verfügung. Das ist das 6-fache der neuen C-Control I. Darüber hinaus läßt sich durch den optimierten OCBASIC-Compiler ein Programm um typisch 20% verkleinern.
- Mehr als 24 Digitalports, 8 AD-Ports mit bis zu 10 Bit Auflösung, 2 DA-Ausgänge, 2 FREQ-Eingänge, BEEP, TEST, IRQ, SDA, SCL, TXD, RXD, CTS, RTS, START und die Status-LEDs sind gleichzeitig nutzbar. Bis zu 16 AD-Ports sind möglich.
- Durch Deaktivierung von Betriebssystemfunktionen stehen bis zu 52 I/O-Ports direkt am Controller zur Verfügung.
- Die Open-Maxi läuft auf der Open-Control M-Unit-Hardware von CCTools, die pinkompatibel zur weitverbreiteten C-Control I Version 1.1 M-Unit ist. Dadurch läßt sich Hardware für die Original-C-Control nutzen.
- Das I²C-LCD wird komfortabel unterstützt. Es stehen die neuen Befehle LCDINIT, LCDCLS, LCDLOCATE, LCDCMD, LCDPUT und LCDPRINT zur Verfügung. Die I²C-Adresse des Portexpanders PCF8574 für das LCD ist änderbar. Dadurch wird das Ansprechen mehrerer LCDs ermöglicht. Die Hintergrundbeleuchtung oder 2. Enable-Leitung lassen sich programmgesteuert setzen.
- Es werden 64 Extended Ports ("EXTPORTs") per I²C-Portexpander PCF8574 unterstützt. Hierbei merkt sich die Open-Maxi die Ausgabe. Daher lassen sich einige Pins eines PCF8574 als Input und andere als Output verwenden. Die Befehle TOG, PULSE und DEACT werden bei den EXTPORTs zwar nicht unterstützt, aber die irrtümliche Verwendung führt nicht dazu, daß wie bei der neuen C-Control I unbeabsichtigt Systemdaten überschrieben werden.
- Die Serielle Schnittstelle arbeitet problemlos mit Baudraten von 300 bis 115200 Baud und einem 32 Byte großen Empfangsbuffer. Mit OMDLWIN wird selbst ein maximal großes Programm in 12 Sekunden übertragen. Hardware-Handshake wird unterstützt.
- 2 DA-Ports mit 8 Bit Auflösung und 2441 Hz PWM-Frequenz. Andere Auflösungen und PWM-Frequenzen lassen sich leicht einstellen. Beispielsweise sind bei 8 Bit Auflösung bis zu 78 kHz möglich. Oder bei 10 Bit immerhin 19,5 kHz. Durch entsprechende Konfiguration sind ohne großen Aufwand bis zu 8 DA-Ports nutzbar.
- Ein 32 Kilobyte großes I²C-EEPROM steht zur Datenspeicherung zur Verfügung. Die Dateioperationen (OPEN# FOR, PRINT#, INPUT#, etc.) werden voll unterstützt und sind im Betriebssystem bereits integriert. Optional läßt sich im Byte-Format speichern und die Daten gehen beim Übertragen eines neuen Programms nicht verloren.
- Die Routinen zur Auswertung des DCF77-Signals befinden sich bereits im Betriebssystem und liefern das Sommerzeit-Flag zurück. Außerdem kann die Auswertung des DCF77-Signals deaktiviert werden, wodurch FREQ1 besser nutzbar ist.
- Der BEEP-Ton kann wie auf der C-Control I Version 1.1 parallel zur Programmausführung ausgegeben werden.
- Unterprogramme können bis zu 32 Ebenen tief verschachtelt werden.
- Mit den neuen Befehlen PEEK, PEEKW, POKE und POKEW können Speicherinhalte gelesen und verändert werden.
- Mittels SLOWMODE ON kann der Bustakt auf 1/16 reduziert werden. Dadurch benötigt der Controller nur noch wenige Milliampere Strom. Da die TPM-Module des Controllers angepaßt werden, funktionieren die zeitabhängigen Funktionen BEEP, PAUSE, TIMER, RTC, DA, DCF77, FREQ, usw. wie bei 20 MHz Bustakt.
- Die I²C-Funktionen werden als Firmwareroutinen zur Verfügung gestellt. Der I²C-Bustakt ist einstellbar. Es sind ca. 345 kHz möglich. Die Open-Maxi führt unter anderem bei I²C-Übertragungsfehlern ein I²C-INIT aus.
- Echtzeituhr ("Real Time Clock") mit Uhrzeit, Datum und Wochentag. Schaltjahre werden korrekt behandelt.
- Die Status-LEDs RUN, ACTIVE und DCF-OK werden vom Betriebssystem wie auf der CC1.1 Main-Unit gesetzt.
- Herausgeführte Referenzspannung und Betriebsspannung des AD-Wandlers.
- Zur Erhöhung des Funktionsumfangs existieren viele Softwaremodule, die bei Bedarf in eigene Programme integriert werden können. Es gibt unter anderem Softwaremodule für Modellbau-Servos, für Grundrechenarten in 32 Bit, für IEEE-Fließkommazahlen ("Gleitkommazahlen"), zur Reproduzierung von Infrarot-Signalen und für 1-Wire Digitalthermometer.
- Fehlende Funktionalität läßt sich durch das offene System meist leicht nachrüsten.
- LOOKTAB arbeitet optional im Byte-Format, dadurch belegen Tabellen nur halb soviel Programmspeicher.
- Leicht zu erlernende 6808-Assemblersprache.
- Durch den in OCBASIC integrierten 6808-Assembler ist die Assemblerprogrammierung auf den OM-Controllern so komfortabel, wie auf keinem anderen C-Control-kompatiblen Controllersystem. Assemblerroutinen belegen nicht mehr 256 Byte Speicher, sondern nur noch soviel wie nötig. Außerdem sind mehrere Assemblermodule gleichzeitig nutzbar.
- Höhere Ausführungsgeschwindigkeit durch neue Tokenbefehle in Verbindung mit OCBASIC.
- Keine Störungen ("glitches") mehr an den Digitalports, da das Betriebssystem nicht wie die neue C-Control I die Richtungsregister vor den Datenregistern setzt.
- Drei freie BYTEPORTs, bei denen alle 8 Ports synchron gesetzt werden. Bei der neuen C-Control I werden hingegen die Ports von BYTEPORT[2] nicht gleichzeitig gesetzt.
- Der PULSE-Impuls hat wie auf der C-Control I Version 1.1 eine Länge von ca. 10 µs.
- Kein Überschreiben von Systemdaten durch Überlauf des Rechen- oder GOSUB-Stacks wie bei der neuen C-Control I möglich.
- Das Betriebssystem läßt sich konfigurieren (durch PrintHex, RunOnErr, End2Host, Dcf77Dis und vieles mehr).
- Fehler beim LCD, bei den EXTPORTs, bei der Datendatei und auf der Seriellen Schnittstelle können ausgewertet werden.
- Fehlerhandling ist in BASIC möglich.
- Fehlerfreie Unterstützung der BASIC-Interruptroutine.
- Auf die Variablen im RAM kann per Pointer zugegriffen werden.
- User-Assemblerroutinen lassen sich in jeden der 25 Interrupts und selbst in den Interpreter einbinden.
- Das Carry-Flag der letzten Berechnung wird zurückgeliefert.
- Das BDC-Interface läßt sich direkt nutzen.
- Der HCS08-Mikrocontroller MC9S08AW60, auf dem die Open-Maxi basiert, läßt sich ohne Einschränkungen nutzen.
- Betriebssystemupdate ist möglich.
- In Assemblerprogrammen sind diverse Firmwareroutinen nutzbar.
- Controller startet nicht mehr automatisch nach Programmdownload, sondern kann über RS232 gestartet werden.
- Controller kann aus BASIC heraus in den Programmiermodus wechseln, unabhängig von der Stellung des AUTOSTART-Jumpers. Der AUTOSTART-Jumper wird nur nach RESET und nach END abgefragt.
- Viele weitere Verbesserungen wie optimierter Aufruf bei SYS, besseres RAND und viele neue interne Variablen.

## Handhabung der OM-Controller

### Die Versorgungsspannung

Auf keinen Fall darf die OM direkt mit 230 Volt Netzspannung verbunden werden. Es ist ausschließlich eine Schutzkleinspannung zu verwenden.
Die Open-Macro arbeitet mit einer stabilisierten Versorgungsspannung von 5 Volt +/- 0,4 Volt. Ein keramischer 100-nF-Kondensator, so nah wie möglich an die Versorgungsspannungs-Pins der OM, verbessert einige elektrische Eigenschaften des Controllers. Des weiteren ist Port[3] sehr empfindlich gegenüber elektromagnetischen Störungen. Aus diesem Grund sollte immer eine Z-Diode 5,1 V an Port[3] gegen Masse mit eingebaut werden. Alternativ läßt sich Überspannung auch mittels herkömmlicher Diode 1N4148 nach VDD (5 Volt) ableiten. Die Versorgungsspannung ist zugleich die Referenzspannung für den Analog-Digital-Umsetzer. Aus diesem Grund sollte die Versorgungsspannung möglichst stabil sein und wenig "Brumm" enthalten.
Die Open-Maxi benötigt eine stabilisierte Versorgungsspannung zwischen 4,4 und 5,5 Volt. Das Betriebssystem ist so konfiguriert, daß der Controller bei einer geringeren Spannung als typisch 4,3 Volt resettet wird. Vorsichtig sein sollte man mit zu hoher Versorgungsspannung. Laut Controllerhersteller kann der AW60 Schaden nehmen, wenn mehr als 5,8 Volt an die Betriebsspannungspins angelegt wird. Die Versorgungs- und Referenzspannung für den Analog-Digital-Umsetzer ist nach außen geführt, kann aber mit zwei Jumpern auf die normalen 5 Volt gelegt werden. Die M-Unit ist mit fünf 100 nF Kondensatoren und einem 47 µF Elko großzügig entkoppelt.

### Die Programmierung

Die OM ist in OCBASIC, CCBASIC, mBasic, Basic++, CCPLUS und Assembler programmierbar. Sie ist also sehr kompatibel zu vorhandenen Programmiersprachen und Tools, die bereits zum Programmieren der C-Control-1 verwendet werden. Welche man davon einsetzt, bleibt jedem selber überlassen. Es wurde aber extra für die OM der neue BASIC-Compiler OCBASIC entwickelt, der das ganze Potential der OM ausschöpft. In dieser Anleitung wird ausschließlich auf OCBASIC näher eingegangen. Da der OCBASIC-Dialekt auf der CCBASIC-Syntax basiert, sollte es keine Schwierigkeiten bereiten, die beschriebenen Codesegmente an CCBASIC für Windows, CCBASIC für DOS oder CCBASIC für Linux anzupassen.

### Pinbelegung der Open-Macro

#### Funktionen der Pins

Serielle Schnittstelle
An diesem Port liegt die Serielle Schnittstelle (RS232), über die Daten eingelesen und ausgegeben werden können. Außerdem wird die OM über diesen Port programmiert. Die Serielle Schnittstelle belegt also nur noch einen Port. Mit Hilfe eines kleinen Interfaces für Semi-Dual-Wire-RS232 verhält sich diese Schnittstelle allerdings genauso, wie eine herkömmliche RS232 mit den zwei Leitungen RXD und TXD. Die Open-Macro besitzt außerdem noch eine hardwaremäßig implementierte 2. Serielle Schnittstelle (ESCI), die vom Betriebssystem unterstützt wird (siehe UseEsci). Die TXD-Leitung der ESCI liegt am PORT[14] und RXD am PORT[13].
PORT[Nummer]
Hierbei handelt es sich um einen digitalen Port. Diese Ports können die Zustände ON (-1) und OFF (0) annehmen. Jeder Port kann als Eingang oder Ausgang fungieren. Siehe Beispiel. PORT[3] ist allerdings nur als Eingang zu verwenden und bei dessen Beschaltung ist zu beachten, daß dieser Port zugleich als HOST/RUN-Pin dient. Nach einem Reset muß dieser Pin auf High-Potential (5 Volt) liegen, sonst arbeitet der Controller das Anwenderprogramm nicht ab, sondern geht in den Hostmodus. Mittels Hostmodus lassen sich über die Serielle Schnittstelle Anwenderprogramme in den Controller übertragen.
AD[Nummer]
Hierbei handelt es sich um einen Analog-Digital-Port. Analoge Spannungen lassen sich in digitale Werte umsetzen. Ein AD-Port kann nur als Eingang verwendet werden und Werte zwischen 0 (0 Volt) und 255 (5 Volt) annehmen.
BEEP
An jedem dieser Ports kann ein Rechtecksignal mit unterschiedlicher Frequenz ausgegeben werden. Durch Anschluß eines Piezo-Schallwandlers (ohne Elektronik) wird ein Ton erzeugt. Es ist normalerweise nicht möglich, daß mehrere BEEP-Ports gleichzeitig einen Ton ausgeben.
FREQ1
Mit diesem Port kann eine Frequenz gemessen werden. Es findet eine Impulszählung statt. Die Fensterbreite ist auf 1 Sekunde festgelegt. Die Frequenzmessung ist nach Programmstart deaktiviert (siehe FREQ). Durch ein entsprechendes Assemblermodul können auch andere Pins zur Impulszählung verwendet werden.
IRQ
Es kann eine Assembler- oder BASIC-Interruptroutine gestartet werden, sobald an diesem Pin eine High-Low-Flanke detektiert wird. Die Interruptfunktionalität ist nach Programmstart deaktiviert.

### Pinbelegung der Open-Maxi

Bild der älteren Version der Open-Maxi

#### Funktionen der Pins

PORT[Nummer]
Hierbei handelt es sich um einen digitalen Port. Diese Ports können die Zustände ON (-1) und OFF (0) annehmen. Jeder Port kann als Eingang oder Ausgang fungieren. Siehe Beispiel.
AD[Nummer]
Hierbei handelt es sich um einen Analog-Digital-Port. Analoge Spannungen lassen sich in digitale Werte umsetzen. Ein AD-Port kann nur als Eingang verwendet werden und Werte zwischen 0 (0 Volt) und 255 (5 Volt) annehmen. Der AD-Wandler bietet wahlweise gerundete 10 Bit oder gerundete 8 Bit.
SDA und SCL
An diesen beiden Pins ist der I²C-Bus nach außen geführt.
START
Nach einem Reset muß dieser Pin auf Low-Potential (0 Volt, Masse) liegen, sonst arbeitet der Controller das Anwenderprogramm nicht ab, sondern geht in den Hostmodus. Mittels Hostmodus lassen sich über die Serielle Schnittstelle Anwenderprogramme in den Controller übertragen. Es befindet sich auch ein AUTOSTART-Jumper auf der Platine, mit dem sich dieser Pin auf Masse legen läßt.
FREQ1 und FREQ2
Mit diesen Ports kann eine Frequenz gemessen werden. Es findet eine Impulszählung statt. Die Fensterbreite ist auf 1 Sekunde festgelegt. FREQ1 ist zugleich der Eingangspin für DCF77. Es muß der invertierte Ausgang eines DCF77-Empfängers angeschlossen werden.
DA[1] und DA[2]
Zwei PWM-Analogausgänge mit 8 Bit Auflösung und 2441 Hz PWM-Frequenz. Damit lassen sich analoge Spannungen erzeugen. Andere Auflösungen und PWM-Frequenzen lassen sich leicht einstellen. Es ist sehr einfach, an diesen beiden Ausgängen ein Servo-Signal auszugeben.
IRQ
Es kann eine Assembler- oder BASIC-Interruptroutine gestartet werden, sobald an diesem Pin eine High-Low-Flanke detektiert wird. Die Interruptfunktionalität ist nach Programmstart aktiviert.
RESET
Durch Legen dieses Pins auf Masse wird der Controller resettet.
RXD, TXD, CTS und RTS
An diesen Pins liegt die Serielle Schnittstelle (RS232), über die Daten eingelesen und ausgegeben werden können. Außerdem wird die Open-Maxi über diese Schnittstelle programmiert. Um ein Programm über die Serielle Schnittstelle in die Open-Maxi zu übertragen, benötigt man einen Pegelumsetzer wie den MAX232, der die 5-Volt-Signale der M-Unit auf die +/- 12 Volt des PCs umsetzt und invertiert. So ein Pegelumsetzer ist zum Beispiel auf dem Programmieradapter "950602" von Conrad Electronic vorhanden. Dieser Programmieradapter ist eigentlich für die C-Control I Version 1.1 M-Unit entworfen worden, kann aber auch mit der Open-Maxi betrieben werden, da sie pinkompatibel ist. Optional läßt sich an der Seriellen Schnittstelle Hardware-Handshake (CTS und RTS) aktivieren. Zu beachten ist, daß PORT[21] mit der Funktion RTS der ersten Seriellen Schnittstelle belegt ist. RTS ist auf Ausgang geschaltet und wird beim Lesen von der Schnittstelle bei den BASIC-Befehlen RXD, GET und INPUT immer auf LOW gesetzt, unabhängig davon, ob der Anwender das Hardware-Handshake aktiviert hat oder nicht.
UREF
Die Referenzspannung für den AD-Wandler. Es befindet sich ein Jumper auf der Platine, mit dem dieser Pin auf 5 Volt gelegt werden kann.
BEEP
An diesem Pin kann ein Rechtecksignal mit unterschiedlicher Frequenz ausgegeben werden. Durch Anschluß eines Piezo-Schallwandlers (ohne Elektronik) wird ein Ton erzeugt. Der BEEP-Ton kann wie auf der C-Control I Version 1.1 parallel zur Programmausführung ausgegeben werden. Allerdings ist die Tonfrequenz um 25% höher.
TEST
Mit diesem Pin kann der Anwender testen, ob der "20-ms-Interrupt" korrekt arbeitet. Es wird ein Rechtecksignal mit 25 Hz Frequenz ausgegeben.
RUN-, ACTIVE- und DCF-OK-LEDs
Die RUN-, ACTIVE- und DCF-OK-LEDs werden vom Betriebssystem gesetzt. Die LEDs sind wie auf der C-Control I Version 1.1 low-aktiv und können mit Vorwiderstand zwischen diesen Pins und 5 Volt geschaltet werden.
VDDAD
Die Spannungsversorgung für den AD-Wandler ("VDDAD") ist separat herausgeführt. Wenn der Anwender dieses Feature nicht benötigt, muß er einen Jumper aufsetzen. Der Jumper muß zwischen VDDAD und 5 Volt gesetzt werden.
AUTOSTART-Jumper
Der AUTOSTART-Jumper liegt rechts von PORT[3] und PORT[4] und mit ihm kann der START-Pin auf Masse gelegt werden. Dadurch startet die Open-Maxi nach Reset und nach END automatisch das Anwenderprogramm. Während der Programmerstellung sollte der Jumper nicht gesetzt werden. Das ist auch nicht notwendig, da die Open-Maxi über die Serielle Schnittstelle gestartet werden kann.
UREF-Jumper
Der UREF-Jumper liegt rechts von BKGD und RESET und mit ihm kann die Referenzspannung für den AD-Wandler auf 5 Volt gelegt werden.
VDDAD-Jumper
Die Spannungsversorgung für den AD-Wandler ("VDDAD") ist separat herausgeführt. Wenn der Anwender dieses Feature nicht benötigt, muß er einen Jumper aufsetzen. Der Jumper muß zwischen die Pins VDDAD und 5 Volt gesetzt werden.
RXD2, TXD2, CTS2 und RTS2
Die Pins für die zweite Serielle Schnittstelle (SCI1-Modul) vom Controller. Sie werden vom Open-Maxi-Betriebssystem nicht benutzt und sind für zukünftige Anwendungen reserviert. Sie können zur Zeit vom Anwender frei verwendet werden.
SS, MISO, MOSI und SPSCK
Die Pins für das "Serial Peripheral Interface" (SPI-Modul) vom Controller. Sie werden vom Open-Maxi-Betriebssystem nicht benutzt und sind für zukünftige Anwendungen reserviert. Sie können zur Zeit vom Anwender frei verwendet werden.
PORT[35] & SERVO1
Mit einem zusätzlichen Assemblermodul kann an diesem Pin ein Servo-Signal ausgegeben werden. Dieser Port wird vom Open-Maxi-Betriebssystem nicht benutzt und kann vom Anwender frei verwendet werden.
PORT[36] & SERVO2
Mit einem zusätzlichen Assemblermodul kann an diesem Pin ein Servo-Signal ausgegeben werden. Dieser Port wird vom Open-Maxi-Betriebssystem nicht benutzt und kann vom Anwender frei verwendet werden.
PORT[53] & KEYB
Dieser Port wird vom Open-Maxi-Betriebssystem nicht benutzt und ist für zukünftige Anwendungen reserviert. Er kann zur Zeit vom Anwender frei verwendet werden.
PORT[19] & MCLK
Dieser Port wird vom Open-Maxi-Betriebssystem nicht benutzt und ist für zukünftige Anwendungen reserviert. Er kann zur Zeit vom Anwender frei verwendet werden.
BKGD
Das "Single-Wire Background Debug Interface" des AW60-Controllers.

### Einfache Programmierschaltung für Open-Macro

Hier ein Schaltplan für eine einfache, vielbewährte Programmierschaltung mit Semi-Dual-Wire-RS232 für die Open-Micro, die aber auch mit der Open-Macro verwendet werden kann. Sie ist sowohl zur Übertragung von Anwenderprogrammen als auch zum Datenaustausch (mittels PRINT, INPUT, etc.) geeignet. Als Transistoren können alle Standard-Kleinsignal-NPN-Typen wie beispielsweise BC547B verwendet werden. Die Werte der Widerstände sollten jedoch nicht verändert werden. Die Schaltung ist mit PORT[1] der OM verbunden. Der Schalter S1 ist der Hostmodeschalter. In Stellung "HOST" verbindet er PORT[3] mit Masse. In Stellung "RUN" wird dieser Port über den Pull-Up-Widerstand R1 auf High-Potential gelegt. Die Schaltung wird mittels Nullmodemkabel an die Serielle Schnittstelle (RS232) eines PCs angeschlossen. Es kann das Nullmodemkabel der C-Control-1 verwendet werden, bei dem die beiden Leitungen RxD und TxD gekreuzt sind. Der Controller läßt sich per "Power-On Reset" (POR), also Einschalten der Betriebsspannung, und per "Low-Voltage Inhibit"-Reset (LVI) resetten. Letzteres wird auf dem zweiten PE-Board gemacht.
Zur bequemen Programmentwicklung sollte das zweite PE-Board oder das Starterboard von CCTools verwendet werden, da es viel umfangreicher ist und eine bessere Testumgebung bietet. Auf diesen Boards wird der Portzustand mittels LEDs angezeigt, die über Porttreiber (4049 oder 4050) versorgt werden und daher, anders als beim Board von Conrad Electronic, nicht die Ports belasten.

Größeres Bild

### Programmieradapter für Open-Maxi

Um ein Anwenderprogramm über die Serielle Schnittstelle in die Open-Maxi zu übertragen, benötigt man einen Pegelumsetzer wie den MAX232, der die 5-Volt-Signale der M-Unit auf die +/- 12 Volt des PCs umsetzt und invertiert. So ein Pegelumsetzer ist zum Beispiel auf dem Programmieradapter "950602" von Conrad Electronic vorhanden. Dieser Programmieradapter ist eigentlich für die C-Control I Version 1.1 M-Unit entworfen worden, kann aber auch mit der Open-Maxi betrieben werden, da sie pinkompatibel ist. Leider bietet Conrad diesen Adapter nicht mehr an, aber viele C-Control-Anwender werden ihn sicherlich noch besitzen.
Hier ein Bild von diesem C-Control BASIC M-Adapter:
Moderne Rechner haben allerdings keine Serielle Schnittstelle mehr. Der Anwender muß deshalb zusätzlich einen USB-nach-Seriell-Adapter einsetzen. Reichelt bietet so einen Adapter unter der Bestellnummer "DELOCK 61425" an. Damit wird unter Windows 7 ein maximal großes Programm in unter 12 Sekunden übertragen. Bei USB-nach-Seriell-Adaptern mit FTDI-Chip kann die Übertragungsgeschwindigkeit bedeutend erhöht werden, indem im Geräte-Manager die Wartezeit bei den BM-Einstellungen auf 1 ms gesetzt wird.
Conrad Electronic bietet unter der Bestellnummer "198834" einen "M-Unit Programmer für CCI-2.0" an, der über eine 5-polige Buchse zum direkten Anstecken einer Open-Maxi verfügt. Allerdings ist er mit RS232-Anschluß schon fast 30 EUR teuer, mit USB ("198318") fast 40 EUR. Leider sind beide genannten Adapter bei Conrad ausverkauft und deshalb seit einiger Zeit nicht mehr erhältlich.
Einige Betatester haben gute Erfahrungen mit dem 15 EUR teuren Voltcraft USB-Programmierkabel "197339" von Conrad Electronic gemacht. Der 4-polige Programmierstecker ist sehr kompakt und stellt auch 5 Volt aus dem USB bereit, womit Schaltungen geringer Stromaufnahme direkt aus dem Programmierkabel versorgt werden können. Die Pegel von RXD und TXD sind direkt CMOS-kompatibel. Allerdings ist der Stecker nicht zur 5-poligen Steckerleiste der Open-Maxi kompatibel, und das Kabel ist mechanisch etwas steif.
Das Bild zeigt den von Jens Gürtler entwickelten preiswerten USB-Programmieradapter für die Open-Maxi auf Basis des FT232R. Wer sich zutraut, SMD zu löten (SSOP28), kann sich diesen Adapter aufbauen. Siehe Schaltbild. Die Treiber für alle gängigen Betriebssysteme kann man bei FTDI herunterladen. Wer bei Reichelt bestellt, kann den Programmer für unter 4 EUR herstellen. Die notwendigen Dateien für Target 3001! gibt es in diesem ZIP-Archiv.
Die aufgeführten Programmieradapter sind sowohl zur Übertragung von Anwenderprogrammen als auch zum Datenaustausch (mittels PRINT, INPUT, etc.) geeignet. Allerdings erreicht man meist nur mit einer "richtigen" Seriellen Schnittstelle die kürzesten Übertragungszeiten. Mit einem USB-nach-Seriell-Wandler benötigt die Übertragung üblicherweise mehr Zeit.

## Programmieren in OCBASIC

Die Beschreibung der Befehle und reservierten Wörter in den folgenden Kapiteln bezieht sich auf den OCBASIC-Compiler. Wird ein anderer Compiler verwendet, gibt es eventuell Einschränkungen bei den Befehlen, bzw. einige Befehle stehen nicht mehr zur Verfügung oder werden anders realisiert. Welche Programmiersprache, bzw. welcher BASIC-Dialekt verwendet wird, bleibt aber natürlich jedem selbst überlassen.
Besonders leicht kommt man über die OCBASIC-Schlüsselwortliste zum gewünschten Befehl.

### Beschreibung

Da das Copyright zu CCBASIC bei Conrad Electronic liegt, wurde während des OM-Projekts der "Open-Control/BASIC-Compiler" entwickelt. Der Compiler ist (soweit sinnvoll) 100% kompatibel zur CCBASIC-Syntax, bietet aber trotzdem viele neue Features wie beispielsweise mehrzeiliges als auch einzeiliges IF, WHILE..WEND, REPEAT..UNTIL, Funktionen und Subroutinen (Prozeduren) in Standardsyntax. Außerdem gibt es eine neue Syntax, mit der BIT-Variablen nicht mehr auf festen Positionen im User-RAM gespeichert werden müssen, sondern innerhalb von BYTE- oder WORD-Variablen als "Bitarrays" abgelegt werden können. Dadurch müssen keine Variablen mehr an festen Positionen plaziert werden. Der Compiler besitzt sogar einen integrierten 6808-Assembler. Damit können BASIC- und Assemblerroutinen innerhalb derselben Sourcecode-Datei erstellt werden. Assemblerroutinen sind so deutlich komfortabler zu erstellen, da in Assembler auf vom Anwender definierte Variablen und auf die meisten internen Variablen direkt zugegriffen werden kann. Assemblerroutinen lassen sich von BASIC aus auf die gleiche Weise aufrufen wie BASIC-Routinen.
Standardmäßig wird Tokencode erzeugt, der die neuen Befehle der OM nutzt und auf diese Weise die Programmgröße um typisch 20% reduziert. Es ist aber auch möglich, zu bisherigen C-Control-Versionen kompatiblen Tokencode mit bis zu 64 KB Größe zu erzeugen. Der Compiler kann statt CCBAS.EXE in die DOS-IDE oder in ConTEXT eingebunden werden.
Es wurde einige Zeit ins Austesten gesteckt und insbesondere darauf geachtet, daß der Compiler möglichst sinnvolle Meldungen ausgibt, falls während der Kompilierung Fehler auftreten. Der Compiler hat eine ausführliche Betatestphase durchlaufen und die offiziell erste Version wurde anhand diverser Beispielprogramme vor der Veröffentlichung ausführlich getestet.

### Entwicklungsumgebungen (IDEs) für OCBASIC

Der Compiler besteht aus der Datei OCBAS.EXE, die sich in beliebige integrierte Entwicklungsumgebungen (IDEs), wie zum Beispiel ConTEXT oder die DOS-IDE von C-Control/BASIC anstelle des C-Control/BASIC-Compilers CCBAS.EXE einbinden läßt. Die IDE stellt einen Texteditor bereit, mit dem der BASIC-Quellcode erstellt und verändert werden kann. Mit einem einfachen Tastendruck läßt sich jederzeit der Compiler starten, der den Quellcode in Tokencode übersetzt. Mit einem ebenfalls in die IDE eingebundenen Downloadprogramm kann dieser Tokencode zum Controller übertragen werden.
Wie die ConTEXT-IDE in eine Entwicklungsumgebung für die Open-Micro, Open-Mini, Open-Midi, Open-Macro und Open-Maxi umfunktioniert werden kann, wird in dieser Dokumentation bei Tips und Tricks ausführlich beschrieben. Für erste Versuche kann der Compiler natürlich auch zunächst auf der MS-DOS-Eingabeaufforderung benutzt werden. In jedem Fall erhält OCBAS.EXE als Eingabe eine BAS-Datei mit dem BASIC-Quellcode und gibt eine DAT-Datei mit dem Tokencode aus. Diese DAT-Datei kann mit einem Downloadtool wie OMDLWIN.EXE, OMDL.EXE oder CCDL.EXE zur OM geschickt werden.
Es gibt zwei Varianten des Compilers: Einmal die 16-Bit-Version OCBAS.EXE und die 32-Bit-Version OCBAS32.EXE. Nur die 32-Bit-Variante ist zu allen Windows-Betriebssystemen kompatibel und sollte deshalb vorzugsweise verwendet werden.
Beim 16-Bit-Compiler OCBAS.EXE handelt es sich um ein DOS-Programm, das auch auf älteren Rechnern benutzbar ist. Aus Kompatiblitätsgründen können dem Programm aber nur kurze DOS-Dateinamen übergeben werden. Die Windows-Betriebssysteme unterstützen das auch bei Dateien mit langem Namen, indem sie jede Datei ebenfalls über einen DOS-Dateinamen ansprechbar machen. Die unter Windows angelegte Datei "Dateiname.bas" kann zum Beispiel mittels "CCBAS datein~1.bas" fehlerfrei übersetzt werden. In der ConTEXT-IDE läßt sich eine Option für kurze DOS-Dateinamen aktivieren. Innerhalb ConTEXT dürfen Quellcode-Dateien daher auch lange Dateinamen besitzen.

### Der echte Compiler OCBASR

Um BASIC-Programme noch weiter zu beschleunigen, wurde für die OM-Controller ein Compiler namens OCBASR erstellt, mit dem der Anwender BASIC-Quellcode sehr komfortabel in Maschinensprache, bzw. Assembler, umwandeln kann. Der Standard-Compiler OCBASIC übersetzt bekanntlich BASIC-Quellcode in Tokencode, der vom Interpreter in der OM ausgeführt wird. Gegenüber diesem interpretierten Tokencode wird die vom Compiler OCBASR erzeugte Maschinensprache erheblich schneller ausgeführt.
Und dabei ist die Benutzung des neuen Compilers denkbar einfach. Zur Installation muß man einfach das Programm OCBASR32.EXE in das Verzeichnis kopieren, in dem schon OCBAS32.EXE steht, und in ConTEXT bei den Benutzerbefehlen "OCBAS32.EXE" durch "OCBASR32.EXE" ersetzen. Nun wird der BASIC-Compiler OCBASR statt OCBASIC gestartet.
Noch einfacher ist es, BASIC-Quellcode in Assemblercode, bzw. Maschinensprache übersetzen zu lassen. Der zu beschleunigende Code muß in einer Subroutine oder in einer Funktion stehen. Wird hinter die Startzeile dieser Subroutine oder Funktion das Schlüsselwort COMPILE angefügt, wird der OCBASR-Compiler aktiv und übersetzt den in ihr stehenden BASIC-Sourcecode in die Maschinensprache. Dieser Programmteil wird nun üblicherweise 3 bis 4 mal schneller ausgeführt. Einige BASIC-Befehle sind sogar 10 bis 20 mal schneller.
Der echte Compiler OCBASR kann auf der offiziellen Infosite zum Open-Control-Projekt heruntergeladen werden.

### Hierarchie der Operatoren

Die Berechnung eines Terms, in dem mehrere Operatoren verwendet werden, erfolgt in einer bestimmten Reihenfolge. Sehr bekannt ist die Hierarchie "Punktrechnung vor Strichrechnung". Der Programmierer kann die Reihenfolge durch Verwendung von Klammern genau festlegen. Auf die Klammerung kann verzichtet werden, wenn die gewünschte Reihenfolge mit der Operatoren-Rangfolge übereinstimmt. Das sollte man aber genau prüfen und im Zweifelsfall besser eine Klammer zuviel setzen.

Rang | Operator | Beschreibung
8 | ( ) | Klammern
7 | + - | positives und negatives Vorzeichen
6 | * / MOD SHL SHR | Multiplikation, Division, Restwert und Schiebebefehle
5 | + - | Addition und Subtraktion
4 | = == <> > >= < <= | numerischer Vergleich
3 | NOT | logisches Vorzeichen
2 | AND NAND | logisches UND
1 | OR NOR XOR | logisches ODER

In einem Term mit mehreren Operatoren werden zuerst die Operationen durchgeführt, die einen hohen Rang besitzen und in der Tabelle am Anfang stehen. Erst danach werden die Rechenergebnisse mit den weiter unten stehenden Operatoren weiterverarbeitet. Die Rangfolge der Operatoren von OCBASIC entspricht exakt denen von CCBASIC.

##### Beispiel

`IF a+b*c>d THEN 'entspricht IF ((a+(b*c))>d) THEN
...
END IF`

Von C-Control-kompatiblen Controllern werden Berechnungen grundsätzlich mit Hilfe eines sogenannten Rechenstacks durchgeführt, der Platz für maximal 7 Elemente bietet. Damit läßt sich das Ergebnis selbst komplexer Terme errechnen. Falls jedoch sehr verschachtelte Ausdrücke berechnet werden müssen, kann der Stack unbemerkt überlaufen, wodurch auf dem Stack gespeicherte Werte verlorengehen. Das berechnete Ergebnis ist dann fehlerhaft. In der Praxis treten Stacküberläufe jedoch so gut wie nie auf, weil komplexe Terme nur sehr selten vorkommen. Das folgende Beispiel benötigt alle 7 Stackelemente, da die einzelnen Berechnungen aufgrund des höheren Rangs nachfolgender Operatoren bis zum Schluß hinausgezögert werden.

##### Beispiel

`PRINT 1 OR 2 + 3 SHL (4 + 5 / SQR(6 + 7))`

### Sprungziele (#)

Sprungziele ("Labels") markieren bestimmte Punkte in der Folge der Programmoperationen. Labels sind Ziele der Sprungoperationen GOSUB und GOTO innerhalb eines Algorithmus. In OCBASIC stehen Labels am Anfang einer Zeile und beginnen wie in CCBASIC stets mit einem Doppelkreuz, dann folgt (ohne Leerzeichen) der Bezeichner des Labels. Zu beachten ist, daß OCBASIC etwas strengere Regeln als CCBASIC für gültige Labelnamen besitzt.
Das folgende Beispiel demonstriert eine Endlosschleife. Wenn man mehrere Labels erstellt, dann kann man im Programm von Label zu Label springen und das BASIC-Programm auf diese Weise verzweigen. Es ist sinnvoll, dem Label einen ausdrucksstarken Namen zu geben, um die Programmübersicht zu wahren.
In OCBASIC kann in vielen Fällen auf Labels und die Befehle GOTO und GOSUB verzichtet werden, weil hinter IF..THEN mehr als ein Befehl angegeben werden darf und die neuen Schleifenbefehle WHILE..WEND und REPEAT..UNTIL existieren. Außerdem lassen sich Funktionen mittels FUNCTION und Subroutinen mittels PROCEDURE definieren. Aber trotzdem wird weiterhin die bekannte und im folgenden Beispiel demonstrierte CCBASIC-Syntax unterstützt.

##### Beispiel

`#endlos 'alternativ kann WHILE TRUE verwendet werden
PRINT funktion
subroutine 'das entspricht GOSUB, nicht GOTO wie in CCBASIC
GOSUB subroutine
GOTO endlos 'alternativ kann WEND verwendet werden
#funktion 'alternativ kann FUNCTION verwendet werden
...
RETURN 123
#subroutine 'alternativ kann PROCEDURE verwendet werden
...
RETURN`

### Bekannte Schlüsselwörter

Die Syntax von OCBASIC entspricht in fast allen Punkten der bekannten Syntax von CCBASIC. Wer bisher die C-Control in CCBASIC programmiert hat, wird sicher keine Schwierigkeiten haben, zu OCBASIC zu wechseln. Trotzdem werden im Folgenden noch einmal die bekannten Schlüsselwörter von CCBASIC im Zusammenhang mit der OM kurz vorgestellt. Eine umfangreiche Beschreibung der CCBASIC-Befehle befindet sich in der Dokumentation zur C-Control Version 1.1 und in der Online-Hilfe von CCBASIC für Windows und DOS.

#### &B

##### Beschreibung

Angabe einer Konstante im binären Zahlensystem. In manchen Fällen ist es übersichtlicher, eine Binärzahl zu verwenden um Port- oder Variablenzustände besser zuordnen zu können.

##### Hinweis

Der Taschenrechner von Windows kann dezimale in binäre und hexadezimale Zahlen umrechnen, wenn er auf wissenschaftliche Ansicht gestellt wird.

##### Syntax

`&B...`

##### Beispiel

`&B10011001`

#### &H

##### Beschreibung

Angabe einer Konstante im hexadezimalen Zahlensystem. In manchen Fällen ist es übersichtlicher, eine Hexzahl zu verwenden um insbesondere Speicheradressen besser zuordnen zu können.
Statt &H kann auch $ verwendet werden.

##### Hinweis

Der Taschenrechner von Windows kann dezimale in binäre und hexadezimale Zahlen umrechnen, wenn er auf wissenschaftliche Ansicht gestellt wird.

##### Syntax

`&H...`

##### Beispiel

`&H1FFE`

#### ABS

##### Beschreibung

Berechnet den Absolutbetrag von "x".

##### Syntax

`ABS(x)`

##### Beispiel

`y = ABS(-1)`

#### AD

##### Beschreibung

Definiert einen Port als analogen Eingang. Daraufhin kann die Spannung am Port mittels Analog-Digital-Umsetzer (ADU) gemessen werden. Der Port liefert standardmäßig Werte zwischen 0 und 255 zurück, was den Spannungswerten 0 Volt bis 5 Volt entspricht. Auf der Open-Macro ist die Versorgungsspannung des Controllers zugleich die Referenzspannung für den Analog-Digital-Umsetzer. Der Innenwiderstand einer am AD-Wandler angeschlossenen Signalquelle sollte laut Controllerhersteller grundsätzlich nicht mehr als 10 kOhm betragen.

##### Hinweis

Die Open-Macro verfügt über interne Pull-Up-Widerstände an den Digitalports, die vom Betriebssystem nach jedem Reset aktiviert werden. Diese Widerstände führen oft zur Verfälschung des AD-Meßwerts, da sie vom Controller vor jeder Messung deaktiviert und nach der Messung wieder aktiviert werden. Deshalb sollten die Widerstände an den entsprechenden Ports mit Hilfe von PULLUPA oder PULLUPB abgeschaltet werden. Die AD-Ports können weiterhin als Digitalports genutzt werden, da das Betriebssystem den Controllerpin nur für die Dauer einer Messung auf den Analog-Digital-Umsetzer umschaltet. Falls diese Vorgehensweise zu Problemen führt, kann der Pin auch dauerhaft auf AD-Funktion geschaltet werden. Dazu sind die AD-Register des Controllers entsprechend zu programmieren. In diesem Fall sind einige Einschränkungen zu beachten, die im Manual zum Controller beschrieben werden.

##### Verfügbarkeit

`Open-Macro: AD[1], AD[2], AD[5], AD[6], AD[9] bis AD[14]
Open-Maxi: AD[1] bis AD[8] und optional AD[9] bis AD[16]`

##### Syntax

`DEFINE bezeichner AD[index]`

##### Beispiel

`DEFINE port1 AD[1]
DEFINE port2 AD[2]
DEFINE port3 AD[3] 'Open-Macro: port3 entspricht port5
DEFINE port4 AD[4] 'Open-Macro: port4 entspricht port6
DEFINE port5 AD[5]
DEFINE port6 AD[6]
'ADCLK=&b00110110 'Open-Macro: AD-Wandler auf 10 Bit umschalten
'ADC1CFG=&b01001000 'Open-Maxi: AD-Wandler auf gerundete 10 Bit
'APCTL1=&b11111111 'Open-Maxi: AD[9] bis AD[16] auf
' AD-Wandlung konfigurieren
PRINT port2`

#### AND

##### Beschreibung

Logische und bitweise UND-Verknüpfung, auch Konjunktion genannt.

a | b | a AND b
0 | 0 | 0
0 | 1 | 0
1 | 0 | 0
1 | 1 | 1

Weitere logische Operatoren sind NOT, NAND, OR, NOR und XOR.

##### Syntax

`AND`

##### Beispiel

`IF x>10 AND x<20 THEN y=x 'y auf x setzen, wenn sowohl x größer
'10 als auch x kleiner 20 ist, x also
'im Wertebereich 11 bis 19 liegt
y = x AND &H7F 'das oberste Bit ausmaskieren`

#### APPEND

##### Beschreibung

Der Befehl wird im Zusammenhang mit OPEN# verwendet. APPEND bedeutet, daß die Datei zum Anhängen von Daten geöffnet wird.

##### Syntax

`APPEND`

##### Beispiel

`OPEN# FOR APPEND`

#### BAUD

##### Beschreibung

Mit dem Befehl wird die Baudrate der Seriellen Schnittstelle eingestellt. Es können beliebige Baudraten eingestellt werden. Auf der Open-Macro wirkt sich dieser Befehl nur auf die Hardware-Schnittstelle (ESCI) aus.

##### Hinweis

Auf der Open-Maxi kann mittels "SCI2BDH=0 : SCI2BDL=11" die Serielle Schnittstelle auf 115200 Baud gesetzt werden. Mittels "SCI2BDH=0 : SCI2BDL=22" auf 57600 Baud.

##### Syntax

`BAUD rate`

##### Beispiel

`'BAUD R38400
'BAUD R19200
BAUD R9600
'BAUD R4800
'BAUD R2400
'BAUD R1200
'BAUD R600
'BAUD R300`

#### BEEP

##### Beschreibung

Auf der Open-Maxi wird mit diesem Befehl ein Interrupt aktiviert, der am BEEP-Pin des Controllers ein Rechtecksignal generiert. Durch Anschluß eines Piezo-Schallwandlers ohne Elektronik wird ein Ton erzeugt. Die Tonfrequenz ist gegenüber der C-Control I Version 1.1 um 25% höher.
Die exakte Frequenz ist
f = 312500 / ton.
Aus gegebener Frequenz läßt sich auch der Parameter "ton" berechnen zu
ton = 312500 / f.
Auf der Open-Maco wurde wie auf der Original-Micro die Befehls-Syntax etwas abgewandelt und es kann daher an fast jedem Digitalport ein Ton ausgegeben werden. Zu beachten ist allerdings, daß während der Tonausgabe der Controller stillsteht und auch keine Interrupts verarbeitet. Aus diesem Grund läuft die interne Echtzeituhr nicht weiter und es ist mit diesem Verfahren nicht möglich, an mehreren BEEP-Ports gleichzeitig einen Ton zu erzeugen.
Da der Parameter "ton" auf der OM nur im Byteformat vorliegt, wurde diese Funktion entsprechend angepaßt. Die höchste Frequenz bei ton=0 ist 27,6 kHz, die niedrigste bei ton=255 ist 16 Hz. Es wird also der gesamte Audiofrequenzbereich abgedeckt. Insbesondere niedrige Frequenzen lassen sich auch gut zur Taktung von Hardware einsetzen.
Die exakte Frequenz ist
f = 3.2E6 / (3*ton^2+17*ton+116).
Aus gegebener Frequenz läßt sich auch der Parameter "ton" berechnen zu
ton = -17/6 + SQR(3.2E6/(3*f)-1103/36).
Zwischentöne sind durch Variation des internen Takts (siehe FREQ2) realisierbar.

##### Hinweis

Auf der Open-Macro hält bei Frequenzen kleiner 25 Hz der Ton länger an als bei "dauer" angegeben, da der zur Generierung des Rechtecksignals verwendete Timer nur am Ende jeder Halbwelle abgefragt wird.

##### Verfügbarkeit

`Open-Macro: PORT[1], PORT[2], PORT[4], PORT[5], PORT[6] und
PORT[9] bis PORT[16]
Open-Maxi: BEEP-Pin`

##### Syntax

`BEEP ton, tondauer, port 'Open-Macro
BEEP ton, tondauer, pause_nach_beep 'Open-Maxi`

##### Beispiel

`'Open-Macro:
DEFINE ton_port PORT[6]
BEEP 250, 50, ton_port '1 Sekunde an PORT[6]
'Open-Maxi:
BEEP 250, 50, 150 '1 Sekunde und 3 Sekunden Pause nach dem Ton`

#### BIT

##### Beschreibung

Mit dem Befehl wird eine Bitvariable definiert. Ein Bit ist die kleinste Speichereinheit und kann die Zustände ON oder OFF annehmen. In OCBASIC sind Adressen, bzw. Index-Positionen zwischen 1 und 256 zulässig.
Alle definierten Bit-, Byte- und Wordvariablen werden im USER-RAM gespeichert und können sich überlagern, wenn bei der Definition irgendeiner Variable ein Index angegeben wird. Mit BIT[1] bis BIT[8] können beispielsweise alle Bits von BYTE[1] einzeln angesprochen werden. Mit BIT[1] bis BIT[16] alle Bits von WORD[1]. Mit BIT[17] beginnt das BYTE[3] und WORD[2]. Die Bitvariablen werden in den ersten 32 Bytes des USER-RAMs abgelegt.
Um dem Anwender die Aufteilung des zur Verfügung stehenden RAM-Speichers zu erleichtern, unterstützt der OCBASIC-Compiler eine neue OF-Syntax, mit der Bitvariablen nicht mehr auf festen Positionen im USER-RAM gespeichert werden müssen, sondern innerhalb von Byte- oder Wordvariablen als Bitfelder ("Bitarrays") abgelegt werden können. Die Byte- oder Wordvariablen lassen sich vom Compiler automatisch verwalten. Durch dieses Verfahren müssen keine Variablen mehr manuell an festen Positionen plaziert werden.

##### Syntax

`DEFINE bezeichner BIT[index]
DEFINE bezeichner BIT[index] OF bytevariable
DEFINE bezeichner BIT[index] OF wordvariable`

##### Beispiel

`DEFINE zahl BYTE[1]
DEFINE bit0 BIT[1] ' Die 8 BITs belegen die gleiche Speicherzelle
DEFINE bit1 BIT[2] ' wie BYTE[1]. Daher ändert sich die Variable
DEFINE bit2 BIT[3] ' "zahl", wenn eine Änderung an den einzelnen
DEFINE bit3 BIT[4] ' BITs vorgenommen wird.
DEFINE bit4 BIT[5]
DEFINE bit5 BIT[6]
DEFINE bit6 BIT[7]
DEFINE bit7 BIT[8]
DEFINE bit7vonzahl BIT[8] OF zahl
zahl=0 'die Variable "zahl" entspricht jetzt binär 00000000
print "Zahl=";zahl
bit0=ON 'die Variable "zahl" entspricht jetzt binär 00000001
bit7=ON 'die Variable "zahl" entspricht jetzt binär 10000001
bit2=ON 'die Variable "zahl" entspricht jetzt binär 10000101
PRINT "Zahl=";zahl
IF bit7vonzahl THEN 'wenn Bit Nummer 7 von "zahl" gesetzt ist, dann
bit5=ON 'setze auch das Bit Nummer 5
ELSE
PRINT "Das Most Significant Bit (MSB) der Variable ist nicht gesetzt."
END IF`

##### Hinweis

Nach Programmstart ohne Fehler wird vom Betriebssystem der gesamte Variablenspeicher mit Ausnahme von VERSION auf 0 gesetzt. Damit alle Variablen auf 0 stehen, sollte der Anwender bei Programmstart VERSION=0 ausführen.

##### Hinweis

Auf der OM ist es guter Programmierstil, alle Variablen vom Compiler OCBASIC automatisch zuweisen zu lassen. Mit der neuen "OF"-Syntax klappt das auch bei BIT-Variablen. Der Controller kann aber nur 256 BIT-Variablen ansprechen und diese müssen in den ersten 256/8=32 Byte des USER-RAMs liegen. Deshalb sollten die BYTE- oder WORD-Variablen, in denen die BIT-Variablen liegen, zu Beginn definiert werden.

#### BYTE

##### Beschreibung

Mit dem Befehl wird eine Byte-Variable definiert. Die Variable kann also einen Wert von 0 bis 255 annehmen. Alle Variablen, die im BASIC-Programm verwendet werden, müssen vorher definiert werden. Bei der Open-Macro stehen 140 Byte-Variablen zur Verfügung. Auf der Open-Maxi sind es sogar 256 Byte-Variablen. Nach Programmstart sind alle Variablen (mit Ausnahme von VERSION) gelöscht, das heißt sie enthalten den Wert 0.

##### Hinweis

Der Anwender sollte bei der manuellen Vergabe von Speichernummern (z.B.: DEFINE var BYTE[1]) besonders vorsichtig sein, denn bei allen vom Compiler automatisch positionierten Variablen werden der Reihe nach Speicherstellen vergeben, wobei alle manuellen Speicherzuweisungen ignoriert werden. Es kann dadurch zu ungewollten Überlagerungen der Variablen und daher zwangsläufig zu Fehlern im Programm kommen. Die manuell zugewiesenen Variablen werden vom Compiler auch nicht der Anzahl der benutzen RAM-Bytes hinzuaddiert.

##### Syntax

`DEFINE bezeichner BYTE[index]
DEFINE bezeichner BYTE`

##### Beispiel

`DEFINE variable BYTE
variable = 13`

##### Hinweis

Nach Programmstart ohne Fehler wird vom Betriebssystem der gesamte Variablenspeicher mit Ausnahme von VERSION auf 0 gesetzt. Damit alle Variablen auf 0 stehen, sollte der Anwender bei Programmstart VERSION=0 ausführen.

#### BYTEPORT

##### Beschreibung

Mit dem Befehl wird ein 8-Bit-Digitalport definiert. Daraufhin können auf der Open-Macro PORT[1] bis PORT[6] und PORT[9] bis PORT[16] im Byteformat angesprochen werden. Das entspricht PORTA und PORTB vom QB8-Controller. Auf der Open-Maxi stehen standardmäßig drei Byteports und bis zu acht Extended Byteports, die mittels acht I²C-Portexpandern PCF8574 realisiert werden können, zur Verfügung.

##### Verfügbarkeit

`Open-Macro: BYTEPORT[1] (die unteren 6 Bits) und BYTEPORT[2]
Open-Maxi: BYTEPORT[1], BYTEPORT[2], BYTEPORT[5] (optional mehr) und
BYTEPORT[9] bis BYTEPORT[16] (Extended Ports)`

##### Syntax

`DEFINE bezeichner BYTEPORT[port]`

##### Beispiel

`DEFINE port_a BYTEPORT[1]
DEFINE port_b BYTEPORT[2]`

##### Hinweis

Die Extended Ports der Open-Maxi:

    1. PCF8574: BYTEPORT[9]  = PORT[65]  bis PORT[72]
    2. PCF8574: BYTEPORT[10] = PORT[73]  bis PORT[80]
    3. PCF8574: BYTEPORT[11] = PORT[81]  bis PORT[88]
    4. PCF8574: BYTEPORT[12] = PORT[89]  bis PORT[96]
    5. PCF8574: BYTEPORT[13] = PORT[97]  bis PORT[104]
    6. PCF8574: BYTEPORT[14] = PORT[105] bis PORT[112]
    7. PCF8574: BYTEPORT[15] = PORT[113] bis PORT[120]
    8. PCF8574: BYTEPORT[16] = PORT[121] bis PORT[128]

Die Befehle TOG, PULSE und DEACT werden bei den Extended Ports nicht unterstützt.

#### CLOSE#

##### Beschreibung

Schließt die Datei, nachdem sie mit OPEN# FOR geöffnet wurde. Benötigt wird der Befehl nur, wenn die Datei verändert worden ist. Der Befehl ist auf der Open-Macro mit Vorsicht zu genießen, da der Controllerhersteller nur 10.000 Schreibzyklen garantiert.

##### Syntax

`CLOSE#`

##### Beispiel

`OPEN# FOR WRITE
PRINT# 123
CLOSE#`

#### CTS

##### Beschreibung

Test, ob die CTS-Leitung aktiv ist. Das dient für Hardware-Handshake (RTS und CTS) an der Seriellen Schnittstelle, das nur die Open-Maxi bietet.
Auf der Open-Macro liefert diese Funktion immer ON zurück.

##### Syntax

`CTS`

##### Beispiel

`IF CTS THEN GET x`

#### DA

##### Beschreibung

Stellt auf der Open-Maxi zwei Digital-Analog-Ports (PWM) mit 8 Bit Auflösung und 2441 Hz PWM-Frequenz bereit. Die PWM kann bis zu 78 kHz bei 8 Bit Auflösung und 20 MHz Bustakt konfiguriert werden. Bei zum Beispiel 10 Bit Auflösung sind immerhin bis zu 19,5 kHz möglich.
Die Open-Macro unterstützt diese Ports standardmäßig nicht. Wenn ein PWM-Port benötigt wird, muß er über ein nachladbares Assembler-Modul realisiert werden.

##### Syntax

`DEFINE bezeichner DA[index]`

##### Beispiel

`DEFINE pwm_port DA[1]
pwm_port=128`

#### DAY

##### Beschreibung

Tag-Wert der Echtzeituhr auf der Open-Maxi.
Die Open-Macro unterstützt standardmäßig keine Datumsfunktion in der Echtzeituhr und die interne Variable DAY liegt deshalb auf dem gleichen RAM-Speicherplatz wie der temporäre Zwischenspeicher zur Frequenzmessung (siehe FREQ1).

##### Syntax

`DAY`

##### Beispiel

`DAY = 1
PRINT DAY`

#### DEACT

##### Beschreibung

Mit dem Befehl wird ein Port, der vorher als Ausgang benutzt wurde, wieder auf Eingang geschaltet, also in den hochohmigen Anfangszustand versetzt.
Die OM besitzt interne Pull-Up-Widerstände, die standardmäßig aktiviert sind und die Digitalports mit High-Potential (5 Volt) verbinden, solange die Ports auf Eingang geschaltet sind.
Die Befehle TOG, PULSE und DEACT werden bei den Extended Ports nicht unterstützt.

##### Syntax

`DEACT port`

##### Beispiel

`DEFINE port1 PORT[1]
DEFINE byteport2 BYTEPORT[2]
port1 = ON
DEACT port1
DEACT byteport2`

#### DEFINE

##### Beschreibung

Mit dem Befehl wird ein Bezeichner definiert. Alle Bezeichner (Ports, Variablen und Konstanten) müssen definiert werden, bevor sie verwendet werden können.
Falls der exakt gleiche Bezeichner mehrfach definiert wird, gibt der Compiler nur eine Warnmeldung aus. Bei gleichnamigen, sonst aber ungleichen Bezeichnern wird während der Übersetzung ein Fehler ausgegeben.

##### Hinweis

Der Anwender sollte bei der manuellen Vergabe von Speichernummern (z.B.: DEFINE var BYTE[1]) besonders vorsichtig sein, denn bei allen vom Compiler automatisch positionierten Variablen werden der Reihe nach Speicherstellen vergeben, wobei alle manuellen Speicherzuweisungen ignoriert werden. Es kann dadurch zu ungewollten Überlagerungen der Variablen und daher zwangsläufig zu Fehlern im Programm kommen. Die manuell zugewiesenen Variablen werden vom Compiler auch nicht der Anzahl der benutzen RAM-Bytes hinzuaddiert.

##### Syntax

`DEFINE bezeichner [AS] art [OF variable]`

##### Beispiel

`DEFINE bitport PORT[2] 'BIT-Port (Digitalport) vereinbaren.
DEFINE variable BYTE[1] 'BYTE-Variable auf der ersten Speicherzelle.
DEFINE b0 BIT[1] OF variable 'BIT-Variable in einer BYTE-Variable ablegen.
DEFINE konstante 64 'Eine symbolische Konstante.
DEFINE sekunde SECOND 'Alternativer Name fuer SECOND.
DEFINE x BYTE 'Eine Variable definieren. Die Speicherzelle
'wird vom Compiler automatisch vergeben.
DEFINE a,b,c BYTE 'Drei Variablen hintereinander ablegen.
DEFINE d,e,f BYTE[5] 'Drei Variablen belegen gleichen Speicher.
a=123
b=a+konstante
PRINT sekunde`

##### Hinweis

Auf der OM ist es guter Programmierstil, alle Variablen vom Compiler OCBASIC automatisch zuweisen zu lassen. Mit der neuen "OF"-Syntax klappt das auch bei BIT-Variablen. Der Controller kann aber nur 256 BIT-Variablen ansprechen und diese müssen in den ersten 256/8=32 Byte des USER-RAMs liegen. Deshalb sollten die BYTE- oder WORD-Variablen, in denen die BIT-Variablen liegen, zu Beginn definiert werden.

##### Hinweis

Um die maximal mögliche Variablenanzahl zu erzielen, müssen im Programm zuerst die BIT-Variablen, dann BYTE, anschließend WORD und schließlich LONG definiert werden.

#### DOW

##### Beschreibung

Wochentag-Wert der Echtzeituhr auf der Open-Maxi.
Die Open-Macro unterstützt standardmäßig keine Datumsfunktion in der Echtzeituhr und die interne Variable DOW liegt deshalb auf dem gleichen RAM-Speicherplatz wie FREQ1.

##### Syntax

`DOW`

##### Beispiel

`IF DOW = 1 THEN PRINT "Montag"
IF DOW = 2 THEN PRINT "Dienstag"
IF DOW = 3 THEN PRINT "Mittwoch"
IF DOW = 4 THEN PRINT "Donnerstag"
IF DOW = 5 THEN PRINT "Freitag"
IF DOW = 6 THEN PRINT "Samstag"
IF DOW = 7 THEN PRINT "Sonntag"`

#### ELSE

##### Beschreibung

Der Befehl wird im Zusammenhang mit IF..THEN verwendet. Falls die bei IF abgefragte Bedingung nicht erfüllt ist, werden die Anweisungen im ELSE-Zweig ausgeführt.

##### Syntax

`ELSE`

##### Beispiel

`IF x = 0 THEN 'wenn x gleich 0 ist,
y = 2 ' dann setze y auf 2 und gehe hinter das "END IF"
ELSE 'wenn x dagegen ungleich 0 war,
y = 13 ' dann setze zunächst y auf 13 und
x = 12 ' danach x auf 12 und
END IF 'fahre mit der Befehlsausführung hinter "END IF" fort`

#### END

##### Beschreibung

Der Befehl beendet die Programmausführung.
Die Open-Macro befindet sich danach in einer Endlosschleife, sofern End2Host nicht aktiviert wurde.
Die Open-Maxi fragt zusätzlich den START-Pin ab und startet das Programm neu, wenn dieser auf Masse liegt.
Durch Angabe eines weiteren Schlüsselworts hinter dem END sind auch andere Bedeutungen denkbar: Das "END IF" entspricht dem "ENDIF" und beendet ein mehrzeiliges IF..THEN. Das "END TABLE" entspricht "TABEND" und beendet eine Datentabelle. Und ein "END SYSCODE" entspricht "SYSEND" und beendet eine SYSCODE-Liste.

##### Syntax

`END`

##### Beispiel

`IF x = 0 THEN END`

#### EOF

##### Beschreibung

Test auf Dateiende beim Auslesen der Datei mittels INPUT#. EOF liefert erst nachdem die Datei geöffnet wurde ein sinnvolles Ergebnis.

##### Syntax

`EOF`

##### Beispiel

`IF EOF THEN GOTO dateiende`

#### FILEFREE

##### Beschreibung

Test auf freien Speicherplatz vor dem Schreiben in die Datei mittels PRINT#. FILEFREE liefert erst nachdem die Datei geöffnet wurde ein sinnvolles Ergebnis.
Wenn FileByte=0, dann wird die Anzahl der noch freien Words in der Datei zurückgeliefert. Ansonsten die Anzahl der noch freien Bytes.

##### Syntax

`FILEFREE`

##### Beispiel

`IF FILEFREE>0 THEN GOTO istnochfrei`

#### FOR TO NEXT

##### Beschreibung

Mit diesen Befehlen läßt sich eine Programmschleife realisieren. Dadurch kann die Programmgröße verringert und die Verständlichkeit des Programmflusses erhöht werden.
Die Variable wird durch das FOR zunächst auf den Anfangswert gesetzt, dann die Anweisungen innerhalb der FOR..NEXT-Schleife ausgeführt und anschließend wird die Variable bei NEXT mit dem Endwert verglichen. Falls die Variable ungleich dem Endwert ist, wird die Variable inkrementiert und es werden die Anweisungen innerhalb der Schleife und das NEXT erneut ausgeführt. Durch die FOR..NEXT-Schleife lassen sich Anweisungen also mehrfach ausführen.
Auf C-Control-kompatiblen Controllern wird anders als in den meisten anderen BASIC-Dialekten der Endwert auf Gleichheit getestet, nicht auf "größer". Dadurch kann der gesamte Wertebereich einer Variable ausgenutzt werden. Außerdem wird der Inhalt der Schleife wenigstens einmal ausgeführt.
Optional läßt sich mittels STEP-Befehl eine Schrittweite für die Inkrementierung angeben. Durch Angabe eines negativen STEP-Werts wird eine Dekrementierung erreicht.

##### Syntax

`FOR variable=anfangswert TO endwert [STEP schrittweite]
anweisungen
NEXT variable`

##### Beispiel

`DEFINE wert BYTE
FOR wert = 0 TO 255
Print "Wert"; wert
NEXT wert
'Das Beispiel entspricht dem folgenden Code:
wert=0
#schleife
Print "Wert"; wert
IF wert=255 THEN GOTO schleifenende
wert=wert+1 'die Schrittweite ist 1, falls kein STEP angegeben wurde
GOTO schleife
#schleifenende`

#### FREQ

##### Beschreibung

Mit dieser internen Variable kann die Frequenz am FREQ-Pin abgefragt werden. Die Messung erfolgt im Hintergrund, parallel zur Programmausführung. Zurückgeliefert wird die Anzahl der innerhalb der Meßzeit von 1 Sekunde aufgetretenen Impulse. Und zwar wird bei jeder fallenden Flanke ein Interrupt ausgelöst.
Auf der Open-Maxi ist die Frequenzmessung direkt nach Programmstart aktiviert.
Auf der Open-Macro wird die Frequenzmessung erst aktiviert, nachdem die Torzeit (Meßzeit) eingestellt wurde. Auf den bisherigen OM-Controllern konnte die Torzeit in 20-ms-Schritten angegeben werden. Wie auf der C-Control 1.1 ist auf der Open-Macro die Torzeit jedoch fix auf 1 Sekunde festgelegt. Die Frequenzmessung muß daher mit dem Befehl "FREQ=50" aktiviert werden. Durch "FREQ=0" oder "FREQ=OFF" läßt sich die Frequenzmessung deaktivieren. Während BEEP und SLOWMODE werden alle Interrupts deaktiviert und deshalb wird auch FREQ nicht mehr aktualisiert. Das Gesagte gilt auch für GET und INPUT an der Single-Wire-RS232 (an PORT[1]).
Achtung: Nach einem Reset muß PORT[3] der Open-Macro auf High-Potential (5 Volt) liegen, sonst geht der Controller in den Hostmodus und arbeitet das BASIC-Programm nicht ab.

##### Verfügbarkeit

`Open-Macro: an PORT[3]
Open-Maxi : an FREQ1`

##### Syntax

`FREQ
FREQ1`

##### Beispiel

`FREQ = 50 'Open-Macro: Torzeit, bzw. Meßzeit: 1 Sekunde
PRINT FREQ`

#### FREQ2

##### Beschreibung

Auf der Open-Maxi dient FREQ2 zur Bestimmung der Frequenz eines Signals am FREQ2-Pin. Siehe FREQ.
Auf der Open-Macro läßt sich mit dieser internen Variable der Systemtakt von 3,2 MHz justieren (kalibrieren). Anders als auf der Conrad-Micro läßt sich FREQ2 auch auslesen. FREQ2 entspricht dem Controller-Register OSCTRIM auf Adresse $38. Mit diesem Register wird die Größe des internen Kondensators verändert, der Verwendung im internen Oszillator findet. Durch Erhöhen des FREQ2-Werts um eins wird auch die Periodendauer um rund 0,2% erhöht. Die Taktfrequenz wird also niedriger. Beim Verringern des FREQ2-Wert verhält es sich entsprechend umgekehrt. Die maximale Abweichung vom benötigten TRIM-Wert liegt somit bei 0,1%.
Mit einem Controller, der mehr als etwa 5% vom Nominaltakt abweicht, kann nicht mehr über die Serielle Schnittstelle kommuniziert werden. Das OSCTRIM-Register wird deshalb vom Betriebssystem nach jedem Reset mit dem vom OSCTRIM.EXE-Programm ermittelten und im Flash-Speicher auf Adresse $ffc0 stehenden Wert geladen, um den Controllertakt auf 3,2 MHz zu trimmen.

##### Syntax

`FREQ2`

##### Beispiel

`PRINT FREQ2
FREQ2=128 'das ist der Defaultwert unmittelbar nach Reset`

##### Hinweis

Die Open-Macro wird über einen internen Oszillator getaktet, der mit einer relativ stabilen Frequenz arbeitet. Vom Controllerhersteller Freescale wird die Abweichung der einmal kalibrierten Frequenz zwar mit bis zu ±5% angegeben, aber diese Angabe bezieht sich auf den gesamten Temperatur- und Versorgungsspannungsbereich. Wird der Controller kalibriert und danach bei konstanter Temperatur und Spannung eingesetzt, ist es denkbar, daß die Echtzeituhr dagegen pro Tag nur um maximal 1,44 Minuten falsch geht. Je niedriger die Versorgungsspannung, desto empfindlicher reagiert der Controller allerdings auf Temperaturschwankungen. Wer eine exakte Zeitbasis benötigt, kann die Open-Macro wie die C-Control I UNIT M 2.0 mit einem externen Taktgeber ausstatten. Dafür muß allerdings ein I/O-Pin geopfert werden und der Stromverbrauch steigt drastisch.

#### GET

##### Beschreibung

Mit dem Befehl kann ein Byte (Zeichen) von der Seriellen Schnittstelle gelesen werden. Das BASIC-Programm wartet dann solange, bis ein Zeichen über die Serielle Schnittstelle empfangen wurde, bevor die Befehlsausführung fortgesetzt wird.
Die Open-Maxi bietet eine in Hardware implementierte Serielle Schnittstelle, die mit einem Empfangsinterrupt und 32 Byte Empfangsbuffer ausgestattet ist.
Die Open-Macro besitzt zwei Serielle Schnittstellen: Die an PORT[1] entspricht der Seriellen Schnittstelle der bisherigen OM-Controller und es gibt eine in Hardware implementierte Serielle Schnittstelle (ESCI) mit Empfangsinterrupt und 8 Byte Empfangsbuffer. Letztere kann mit UseEsci=ON aktiviert werden.
Auf der Open-Macro an der PORT[1]-Schnittstelle ist zu beachten, daß während des Wartens keine Interrupts verarbeitet werden. Aus diesem Grund läuft die interne Echtzeituhr nicht weiter.

##### Syntax

`GET variable`

##### Beispiel

`DEFINE variable BYTE
GET variable
PRINT "gelesen wurde ";variable`

#### GOSUB

##### Beschreibung

Mit dem Befehl wird eine Unterroutine aufgerufen. Die Unterroutine wird durch einen RETURN-Befehl beendet und anschließend die Programmausführung mit dem Befehl hinter dem GOSUB fortgesetzt. Innerhalb einer Unterroutine läßt sich eine andere Unterroutine aufrufen. Die Verschachtelung von Subroutinen (die Größe des GOSUB-Stacks) ist bei der Open-Macro auf acht Ebenen und bei der Open-Maxi auf 32 Ebenen begrenzt. Eine davon wird für den Aufruf von BASIC-Interruptroutinen benötigt.
Statt Unterroutine sind auch die Bezeichnungen Subroutine, Prozedur und Unterprogramm üblich. Eine Sonderform der Unterroutine ist die Funktion. Auch zum Aufruf einer Funktion wird intern ein GOSUB verwendet.

##### Syntax

`GOSUB label`

##### Beispiel

`GOSUB unterprogramm1
unterprogramm2 'entspricht GOSUB unterprogramm2
PRINT "Programmende"
END
#unterprogramm1
PRINT "Unterprogramm 1 aufgerufen"
RETURN
PROCEDURE unterprogramm2
PRINT "Unterprogramm 2 aufgerufen"
RETURN
END PROCEDURE`

#### GOTO

##### Beschreibung

Mit dem Befehl wird ein Programmsprung realisiert. Das BASIC-Programm arbeitet dann hinter dem Label weiter.

##### Syntax

`GOTO label`

##### Beispiel

`#endlos
PRINT "Endlosschleife"
GOTO endlos`

#### HANDSHAKE

##### Beschreibung

Auf der OM wurde der HANDSHAKE-Befehl wie bei der C-Control I Version 2.0 umfunktioniert, um Zeigeroperationen (bzw. Array-Funktionen) zu ermöglichen. Er darf daher nicht verwendet werden.
Die C-Control I Version 1.1 wird veranlaßt, das Hardware-Handshake auf der RTS- und CTS-Leitung an der Seriellen Schnittstelle zu aktivieren.

##### Syntax

`HANDSHAKE ON
HANDSHAKE OFF`

##### Beispiel

`HANDSHAKE ON`

#### HOUR

##### Beschreibung

Stundenwert der Echtzeituhr.
Auf der Open-Maxi nimmt diese interne Variable Werte von 0 bis 23 an. Der Wert 24 wird nie erreicht, sondern die DAY-Variable automatisch hochgezählt, da ein neuer Tag begonnen hat. Die Open-Macro unterstützt standardmäßig keine Datumsfunktion in der Echtzeituhr. Deshalb zählt der Stundenwert über 23 hinaus bis 255. Das hat den Vorteil, daß die Echtzeituhr erst nach 10 Tagen und 16 Stunden wieder auf Null steht. Außerdem kann der Anwender vor der Abfrage der Uhrzeit einen Tageswechsel erkennen, die Echtzeituhr also beliebig erweitern, sofern das erforderlich ist.

##### Syntax

`HOUR`

##### Beispiel

`'auf Open-Macro:
PRINT HOUR
IF HOUR>23 THEN 'Tageswechsel erkennen
HOUR=0
tag=tag+1
END IF`

#### IF

##### Beschreibung

Mit dem Befehl läßt sich eine bedingte Befehlsausführung realisieren. Der Befehl vergleicht eine Bedingung auf wahr (ungleich Null) oder unwahr (gleich Null). Die Bedingung ist also ein logischer Ausdruck. Nach dem Vergleich kann festgelegt werden, wie es weitergehen soll. Wenn die Bedingung wahr ist, werden die Befehle im THEN-Zweig ausgeführt. Falls die Bedingung unwahr ist, wird, sofern vorhanden, mit ELSEIF, ELSE oder hinter dem ENDIF weitergemacht. Ein einzeiliges IF darf nicht mit ENDIF beendet werden, kann aber im THEN- und ELSE-Zweig, anders als in CCBASIC, mehrere Anweisungen enthalten.

##### Syntax

`IF bedingung THEN anweisungen1 [ELSE anweisungen2] 'einzeiliges IF
IF bedingung1 THEN 'mehrzeiliges IF
anweisungen1
[ELSE IF bedingung2 THEN
anweisungen2]
[ELSE
anweisungen3]
END IF`

##### Beispiel

`IF x THEN END 'beende das Programm, wenn x ungleich Null ist
IF i=0 THEN
PRINT "Null";
ELSE IF i=1 THEN 'statt "ELSE IF" kann auch "ELSEIF" und
PRINT "Eins"; 'statt "END IF" auch "ENDIF" geschrieben werden
ELSE IF i=2 THEN
PRINT "Zwei"; 'ausserdem ist das "THEN" bei "IF" optional
ELSE IF i=3 THEN
PRINT "Drei";
ELSE IF i=4 OR i=5 THEN
PRINT "Vier oder Fuenf";
ELSE IF i>=10 THEN
PRINT "groesser oder gleich 10";
ELSE
PRINT "Nichts von alledem."
END IF`

##### Hinweis

Wie in CCBASIC ist es möglich, auch in OCBASIC die Syntax "IF bedingung THEN label" zu benutzen. In CCBASIC wird ein unbedingter Sprung zum Sprungziel ausgeführt, wenn die Bedingung erfüllt ist. Das gilt in OCBASIC jedoch nur, wenn die Programmzeile unmittelbar hinter diesem IF-Konstrukt endet oder aber ein "ELSE" folgt. In allen anderen Fällen wird ein Subroutinenaufruf kodiert. Der Anwender sollte deshalb bei diesem IF-Konstrukt sicherheitshalber ein GOTO oder GOSUB vor dem Label angeben, um sicherzustellen, daß wie gewünscht übersetzt wird.

#### INPUT

##### Beschreibung

Einlesen eines Zahlenwertes im ASCII-Textformat von der Seriellen Schnittstelle. Der INPUT-Befehl wartet solange, bis eine komplette Eingabe, beendet mit Carriage Return (CR, ASCII-Code 13) oder einem anderen Sonderzeichen kleiner "0", empfangen wurde. In einem Terminalprogramm wird Carriage Return von der Eingabe-Taste, auch Enter oder Return genannt, generiert.
Zu beachten ist, daß auf der Open-Macro bei der PORT[1]-Schnittstelle während des Wartens auf ein Zeichen keine Interrupts verarbeitet werden. Aus diesem Grund läuft die interne Echtzeituhr nicht weiter.

##### Syntax

`INPUT variable`

##### Beispiel

`DEFINE variable BYTE
PRINT "Bitte eine Zahl eingeben und mit der Eingabe-Taste bestätigen: ";
INPUT variable
PRINT "Es wurde die Eingabe ";variable;" erkannt."`

##### Hinweis

"PRINT zahl" läßt sich nicht per "INPUT" empfangen. Es bleibt ein "Line Feed" (LF, ASCII-Code 10) im Empfangsbuffer zurück. Es muß "PRINT zahl; : PUT 13" verwendet werden. INPUT ist dazu gedacht, um mit CR abgeschlossene Zahleneingaben per Terminal-Programm vom PC zur OM zu senden. Von einem OM-Controller zum anderen lassen sich Zahlen sinnvoller mittels PUT und GET übertragen.

#### INPUT#

##### Beschreibung

Einlesen eines Zahlenwertes (Word) aus der Datei.
Bei FileByte=ON wird ein Byte aus der Datei gelesen.

##### Syntax

`INPUT# variable
INPUT#`

##### Beispiel

`INPUT# variable
PRINT variable
PRINT INPUT#`

#### INTERRUPT

##### Beschreibung

Vereinbart eine BASIC-Interruptroutine. Sie startet normalerweise, wenn am IRQ-Pin eine negative Flanke detektiert wird. Beendet wird die Routine mit RETURN INTERRUPT.
Auf der Open-Macro: Wenn die Interruptroutine starten soll, wenn am IRQ-Pin eine negative Flanke detektiert wird, dann muß zunächst diese Funktionalität im CONFIG2-Register des Controllers aktiviert werden. Das Register läßt sich nach jedem Reset nur einmal beschreiben ("write once"), nachfolgendes Beschreiben wird ignoriert. Nach Aktivieren der IRQ-Funktion läßt sich der Port nicht mehr als Digitalport oder zur Frequenzmessung verwenden.
Um die BASIC-Interruptroutine starten zu können, wird ein Eintrag auf dem GOSUB-Stack benötigt. Wenn kein Eintrag zur Verfügung steht, wird der Fehler "Zu viele GOSUB-Verschachtelungen" erzeugt und, wenn RunOnErr=0 ist, die Programmabarbeitung abgebrochen.
Mit Hilfe eines kleinen Assemblermoduls läßt sich die BASIC-Interruptroutine zum Beispiel auch periodisch in einem bestimmten Zeitabstand starten ("ON TIMER"-Funktion) oder dann, wenn sich der Zustand an einem Digitalport verändert ("Keyboard Interrupt").

##### Syntax

`INTERRUPT label
INTERRUPT OFF`

##### Beispiel

`'für Open-Macro:
INCLUDE "omac.def"
CONFIG2=&b01000000 'IRQEN im CONFIG2-Register des Controllers setzen
INTERRUPT basicirq 'BASIC-Interruptroutine vereinbaren
WHILE TRUE 'Hauptprogramm
...
WEND
PROCEDURE basicirq 'Interruptroutine
PRINT "Interrupt"
RETURN INTERRUPT
END PROCEDURE`

#### LOOKTAB

##### Beschreibung

Lesen eines Wertes (Word) aus einer Tabelle. Der erste Wert aus der Tabelle steht auf der Index-Position 0.
Auf den bisherigen OM-Controllern arbeitete LOOKTAB bisher im 8-Bit-Format. Es wurde also immer ein Byte aus einer Tabelle ausgelesen. Auf der Open-Macro und Open-Maxi arbeitet LOOKTAB jedoch im 16-Bit-Format. Es wird wie auf der "großen" C-Control üblich, ein Word aus der Tabelle ausgelesen. Es gibt jedoch den neuen Befehl LOOKTABBYTE, mit dem Daten aus einer Byte-Tabelle ausgelesen werden können. Um besser nachvollziehen zu können, was der Code bewirkt, gibt es der Vollständigkeit halber auch ein LOOKTABWORD, das aber genauso arbeitet wie LOOKTAB.

##### Syntax

`LOOKTAB tabellenbezeichner, index, variable
LOOKTAB(tabellenbezeichner, index)`

##### Beispiel

`LOOKTAB tabelle1, mess, temp
PRINT LOOKTAB(tabelle1, mess)
END
TABLE tabelle1 WORD
1234 -9 34 211
END TABLE`

#### LOOKTABBYTE

##### Beschreibung

Lesen eines Wertes (Byte) aus einer Tabelle. Der erste Wert aus der Tabelle steht auf der Index-Position 0.

##### Syntax

`LOOKTABBYTE tabellenbezeichner, index, variable
LOOKTABBYTE(tabellenbezeichner, index)`

##### Beispiel

`LOOKTABBYTE tabelle1, mess, temp
PRINT LOOKTABBYTE(tabelle1, mess)
END
TABLE tabelle1 BYTE
122 95 34 211
END TABLE`

#### MAX

##### Beschreibung

Ermittlung des größeren Wertes.

##### Syntax

`MAX(x,y)`

##### Beispiel

`z = MAX(x, 10)`

#### MIN

##### Beschreibung

Ermittlung des kleineren Wertes.

##### Syntax

`MIN(x,y)`

##### Beispiel

`z = MIN(x, 10)`

#### MINUTE

##### Beschreibung

Minuten-Wert der Echtzeituhr.

##### Syntax

`MINUTE`

##### Beispiel

`PRINT MINUTE`

#### MOD

##### Beschreibung

Operator für Modulodivision. Es wird also der Rest einer ganzzahligen Division zurückgeliefert.

##### Syntax

`MOD`

##### Beispiel

`PRINT 10 MOD 6 '10 durch 6 ist 1, der Rest ist 4
printdiv 22,7 '22 durch 7 mit Nachkommastellen
END
DIM i,t1,t2 BYTE
PROCEDURE printdiv(t1,t2)
PRINT t1/t2;
PUT ASC(".")
FOR i=0 TO 9
t1=(t1 MOD t2)*10
PUT ASC("0")+t1/t2
NEXT i
RETURN
END PROCEDURE`

#### MONTH

##### Beschreibung

Monats-Wert der Echtzeituhr.
Die Open-Macro unterstützt standardmäßig keine Datumsfunktion in der Echtzeituhr und die interne Variable MONTH liegt deshalb auf dem gleichen RAM-Speicherplatz wie der temporäre Zwischenspeicher zur Frequenzmessung (siehe FREQ1).

##### Syntax

`MONTH`

##### Beispiel

`PRINT MONTH`

#### NAND

##### Beschreibung

Logische und bitweise UND-Verknüpfung mit anschließender Negation (1er Komplement).

a | b | a NAND b
0 | 0 | 1
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0

Weitere logische Operatoren sind NOT, AND, OR, NOR und XOR.

##### Syntax

`NAND`

##### Beispiel

`x = a NAND b`

#### NOR

##### Beschreibung

Logische und bitweise ODER-Verknüpfung mit anschließender Negation (1er Komplement).

a | b | a NOR b
0 | 0 | 1
0 | 1 | 0
1 | 0 | 0
1 | 1 | 0

Weitere logische Operatoren sind NOT, AND, NAND, OR und XOR.

##### Syntax

`NOR`

##### Beispiel

`x = a NOR b`

#### NOT

##### Beschreibung

Logische und bitweise Negation (1er Komplement). Jedes Bit des Operanden wird invertiert (umgedreht, getoggelt).

a | NOT a
OFF (gleich 0) | ON (gleich -1)
ON (gleich -1) | OFF (gleich 0)
1 | -2

Weitere logische Operatoren sind AND, NAND, OR, NOR und XOR.

##### Syntax

`NOT`

##### Beispiel

`x = NOT y`

#### OFF

##### Beschreibung

Vordefinierte Konstante für 0, also logisch unwahr. Es kann auch die Konstante FALSE verwendet werden.

##### Syntax

`OFF`

##### Beispiel

`Led = OFF`

#### ON

##### Beschreibung

Vordefinierte Konstante für -1 (oder &HFFFF), also logisch wahr. Diese Konstante ist gleichbedeutend mit TRUE.

##### Hinweis

In allen BASIC-Dialekten liefern logische Ausdrücke wie "a>10" oder "7<=9" entweder den Wert -1 oder 0 zurück, je nachdem, ob sie erfüllt oder nicht erfüllt sind. Die liefern also nicht 1 und 0 zurück, wie zum Beispiel in C. Im Zweierkomplement entspricht -1 der vorzeichenbehafteten Integerzahl, bei der alle Bits gesetzt sind. Aus diesem Grund ist es in BASIC nicht erforderlich, logische Operatoren von binären Operatoren zu unterscheiden. Auch für logische Operationen können die binären Operatoren verwendet werden. Ein weiterer Vorteil sind Verknüpfungsmöglichkeiten wie "a AND b<10". In diesem Fall liefert der Ausdruck den Wert a zurück, wenn b kleiner 10 ist, andernfalls wird 0 zurückgeliefert.

##### Syntax

`ON`

##### Beispiel

`Led = ON`

#### ON GOSUB

##### Beschreibung

Unterroutinenaufruf in Abhängigkeit von x. Wenn x gleich 0 ist, wird das erste Label der Liste aufgerufen.

##### Hinweis

In OCBASIC kann für "x" anders als in CCBASIC jeder beliebige Ausdruck verwendet werden. Allerdings führt das zu unnötig langen Programmen. Sinnvollerweise sollte deshalb der Ausdruck einer Variablen zugewiesen und anschließend diese Variable abgefragt werden.

##### Syntax

`ON x GOSUB`

##### Beispiel

`ON x GOSUB label1, label2, label3`

#### ON GOTO

##### Beschreibung

Programmsprung in Abhängigkeit von x. Wenn x gleich 0 ist, wird das erste Label der Liste aufgerufen.

##### Hinweis

In OCBASIC kann für "x" anders als in CCBASIC jeder beliebige Ausdruck verwendet werden. Allerdings führt das zu unnötig langen Programmen. Sinnvollerweise sollte deshalb der Ausdruck einer Variablen zugewiesen und anschließend diese Variable abgefragt werden.

##### Syntax

`ON x GOTO`

##### Beispiel

`ON x GOTO label1, label2, label3`

#### OPEN#

##### Beschreibung

Die zur permanenten Datenspeicherung vorgesehene Datei öffnen. Bei der Open-Maxi wird in einem externen 32 kB großen I²C-EEPROM gespeichert. Bei der Open-Macro werden die Daten hingegen im internen Flash-Speicher des Controllers abgelegt. In beiden Fällen gehen die Daten auch nach Entfernen der Betriebsspannung nicht verloren. Es stehen die Modi WRITE, APPEND und READ zur Verfügung.
Mit OPEN# FOR WRITE wird die Datei zunächst gelöscht und alle per FILEFREE und PRINT# in die Datei geschriebenen Daten überschreiben unwiederbringlich die alten Daten. Erst nach CLOSE# wird der geänderte Dateiende-Zeiger dauerhaft gespeichert.
Mit OPEN# FOR APPEND werden neue Daten per FILEFREE und PRINT# an die bereits in der Datei stehenden angehängt. Erst nach CLOSE# wird der geänderte Dateiende-Zeiger dauerhaft gespeichert.
Mit OPEN# FOR READ können die in der Datei stehenden Daten mittels EOF und INPUT# ausgelesen werden. Der Befehl CLOSE# ist überflüssig und wird ignoriert.
Auf der Open-Macro gehen die gespeicherten Daten beim Übertragen eines neuen Programms in den Controller verloren. Bei der Open-Maxi bleiben hingegen die Daten erhalten.

##### Syntax

`OPEN#`

##### Beispiel

`OPEN# FOR WRITE
IF FILEFREE>0 THEN PRINT# 123
CLOSE#`

#### OR

##### Beschreibung

Logische und bitweise ODER-Verknüpfung, auch Disjunktion genannt.

a | b | a OR b
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 1

Weitere logische Operatoren sind NOT, AND, NAND, NOR und XOR.

##### Syntax

`OR`

##### Beispiel

`y = a OR b`

#### PAUSE

##### Beschreibung

Programmunterbrechung für t*20 Millisekunden.
Dieser Befehl vermindert für die Dauer der Wartezeit die Stromaufnahme der CPU. Intern wird der Assemblerbefehl WAIT ausgeführt, wodurch auf den nächsten Interrupt gewartet wird.
Der Befehl "PAUSE 0" wartet überhaupt nicht.
Der Befehl "PAUSE t" wartet zwischen (t-1)*20 ms und t*20 ms.

##### Syntax

`PAUSE t`

##### Beispiel

`PAUSE 50 '1 Sekunde Pause`

#### PORT

##### Beschreibung

Definiert einen Digitalport. Der Port kann den Zustand 0 (OFF, 0 Volt, GND, Low-Potential) oder -1 (ON, 5 Volt, VDD, High-Potential) annehmen.
Bei Programmstart nach einem Reset sind alle Digitalports auf Eingang geschaltet. Standardmäßig werden die Ports dann durch Pull-Up-Widerstände, die sich im Controller befinden, auf High-Potential gelegt. Sobald einem Digitalport ein Wert zugewiesen worden ist, ist dieser auf Ausgang geschaltet und wird vom Controller niederohmig auf 0 Volt oder 5 Volt gelegt ("Push/Pull").
Open-Macro: Die Pull-Up-Widerstände lassen sich bei Bedarf durch PULLUPA und PULLUPB abschalten, wodurch die Digitalports sehr hochohmig werden. Die Ports sind in der "Push/Pull"-Betriebsart in der Lage, relativ hohe Ströme zu liefern, bzw. nach Masse abzuleiten. Laut Datenblatt dürfen es kurzzeitig maximal 15 mA an PORT[9] bis PORT[16] und sogar 25 mA an PORT[1] bis PORT[6] sein. Im sicheren Bereich arbeitet man aber nur, wenn die Summe der Ströme an allen Ports auf 50 mA beschränkt ist.
Open-Maxi: Die Pull-Up-Widerstände lassen sich durch PTAPE, PTBPE und PTEPE abschalten, wodurch die Digitalports sehr hochohmig werden.
Auf der Open-Maxi stehen außerdem bis zu 64 Extended Ports zur Verfügung, die mittels acht I²C-Portexpandern PCF8574 realisiert werden können.
Siehe auch OFF, ON, DEACT, TOG, PULSE, BYTEPORT, WORDPORT, PULLUPA und PULLUPB.

##### Verfügbarkeit

`Open-Macro: PORT[1] bis PORT[6] und PORT[9] bis PORT[16]
Open-Maxi: PORT[1] bis PORT[16] und PORT[33] bis PORT[40] (optional mehr)
PORT[65] bis PORT[128] (Extended Ports)`

##### Syntax

`DEFINE bezeichner PORT[index]`

##### Beispiel

`DEFINE taste PORT[2] 'an diesem Port muß eine Taste angeschlossen werden
'(siehe "Beschaltung von Eingangsports", Bild 1)
DEFINE led PORT[4] 'an diesem Port muß eine LED angeschlossen werden
'(siehe "Beschaltung von Ausgangsports", Bild 1)
WHILE taste 'führe die Schleife aus, solange Taste nicht gedrückt
led=ON
PAUSE 10
led=OFF
PAUSE 10
WEND
END`

##### Hinweis

Die Extended Ports der Open-Maxi:

    1. PCF8574: BYTEPORT[9]  = PORT[65]  bis PORT[72]
    2. PCF8574: BYTEPORT[10] = PORT[73]  bis PORT[80]
    3. PCF8574: BYTEPORT[11] = PORT[81]  bis PORT[88]
    4. PCF8574: BYTEPORT[12] = PORT[89]  bis PORT[96]
    5. PCF8574: BYTEPORT[13] = PORT[97]  bis PORT[104]
    6. PCF8574: BYTEPORT[14] = PORT[105] bis PORT[112]
    7. PCF8574: BYTEPORT[15] = PORT[113] bis PORT[120]
    8. PCF8574: BYTEPORT[16] = PORT[121] bis PORT[128]

Die Befehle TOG, PULSE und DEACT werden bei den Extended Ports nicht unterstützt.

#### PRINT

##### Beschreibung

Ausgabe von Werten und Texten über die Serielle Schnittstelle.
PRINT ohne abschließendes Semikolon führt zu einer zusätzlichen Übertragung der ASCII-Codes 13 und 10 (Carriage Return und Line Feed). Mehrere Parameter können durch Komma oder Semikolon voneinander getrennt angegeben werden. Ein Komma fügt dabei ein Tabulatorzeichen ein.
Die Kurzform von PRINT ist ein Fragezeichen ("?").

##### Syntax

`PRINT wert
PRINT "Hallo Welt!"
PRINT wert;
PRINT "Hallo Welt!";`

##### Beispiel

`PRINT "Anzeige = "; wert`

#### PRINT#

##### Beschreibung

Schreiben eines Wertes (Word) in die Datei.
Bei FileByte=ON wird ein Byte in die Datei geschrieben.

##### Hinweis

Open-Macro:
Nachdem die OM ein Byte in die Datei geschrieben hat, wird kontrolliert, ob das Byte fehlerfrei in den User-Flash programmiert werden konnte. Ist das nicht der Fall, weil zum Beispiel der Flash-Speicher erschöpft ist, wird ein File-I/O-Fehler ausgelöst, der normalerweise die Programmausführung unterbricht. Der Fehler kann aber auch vom Anwender mittels RunOnErr ausgewertet werden. In diesem Fall bleibt das Interruptsystem deaktiviert und einige Bytes im User-RAM werden nicht restauriert.
Wenn der Anwender hingegen versucht, auf eine Adresse außerhalb des User-Flashs zu schreiben, weil z.B. PRINT# unkorrekterweise ohne vorheriges OPEN# benutzt wurde, wird das Schreiben nicht ausgeführt, um unter anderem das Betriebssystem vor dem Überschreiben zu schützen. Bei einem Schreibversuch außerhalb des User-Flash wird jedoch nicht in jedem Fall ein File-I/O-Fehler ausgelöst.
Weiterhin ist zu beachten, daß im User-Flash nicht nur die Datei, sondern auch das Anwenderprogramm gespeichert wird. Unkorrekte Benutzung von PRINT# kann daher das Anwenderprogramm überschreiben.
Open-Maxi:
Es wird in das 32 kB große externe I²C-EEPROM geschrieben.

##### Syntax

`PRINT# ausdruck`

##### Beispiel

`OPEN# FOR APPEND
IF FILEFREE>0 THEN PRINT# 123
CLOSE#`

#### PULSE

##### Beschreibung

Ausgabe eines Pulses an einem Digitalport. Der Port muß vorher mittels "port = ON" oder "port = OFF" aktiviert worden sein und wird durch PULSE zweimal geTOGgelt. Die Pulsbreite beträgt auf der Open-Macro mindestens 4 µs und auf der Open-Maxi 10 µs.
Die Befehle TOG, PULSE und DEACT werden bei den Extended Ports nicht unterstützt.

##### Verfügbarkeit

`Open-Macro: PORT[1], PORT[2], PORT[4], PORT[5], PORT[6] und
PORT[9] bis PORT[16]
Open-Maxi: PORT[1] bis PORT[16] und PORT[33] bis PORT[40] (optional mehr)`

##### Syntax

`PULSE port`

##### Beispiel

`led=OFF
PULSE led`

#### PUT

##### Beschreibung

Ausgabe eines Bytes über die Serielle Schnittstelle.

##### Syntax

`PUT wert`

##### Beispiel

`PUT x`

#### RAND

##### Beschreibung

Zufallszahl im Integerformat generieren.
Die interne Variable RAND belegt auf der OM den gleichen RAM-Speicher wie DBNZCTR und ERR.

##### Hinweis

Der Algorithmus zur Generierung der Zufallszahlen ("Methode der linearen Kongruenz") ist auf der Open-Macro und Open-Maxi deutlich besser als auf der C-Control, aber systembedingt wird immer wieder die gleiche aus 65536 Elementen bestehende Folge von Pseudo-Zufallszahlen generiert. RANDOMIZE verschiebt nur den Beginn der Folge. Echte Zufallszahlen zu generieren ist gar nicht so einfach. Dazu könnte man zum Beispiel eine Variable schnell hochzählen, bis der Anwender eine Taste losläßt.
Mit der Methode der linearen Kongruenz wird das nächste Glied der Folge aus dem vorherigen allgemein berechnet zu
x[i+1] = (a*x[i]+1) mod m .
Die Open-Macro und Open-Maxi benutzen die Gleichung
x=(3421*x+1) mod 65536 .
Welche Eigenschaften die durch "Methode der linearen Kongruenz" erzeugten Pseudo-Zufallzahlen genau besitzen kann in Fachliteratur wie beispielsweise Donald Knuth, The Art of Computer Programming, Vol. 2, USA 1981 (Addison-Wesley) nachgelesen werden. Um den Wertebereich der erzeugten Zufallszahlen einzuschränken ist MOD offensichtlich nicht so gut geeignet wie eine Division, da die hochwertigsten Bits den größten Zufallscharakter besitzen. Beispielsweise erzeugt die OM mittels "(RAND SHR 14) AND 3" brauchbare Zufallszahlen zwischen 0 und 3.

##### Syntax

`RAND`

##### Beispiel

`x = RAND`

##### Hinweis

Wenn gute Zufallszahlen von 0 bis 5 generiert werden sollen, muß man etwas trickreich vorgehen: Da die Open-Macro und Open-Maxi Zufallszahlen von -32768 bis +32767 erzeugen, müssen diese zunächst in den positiven Zahlenbereich transformiert werden. Das geht mittels "(RAND SHR 1)+16384". Dadurch werden Zufallszahlen von 0 bis 32767 generiert. Es muß nun noch geeignet dividiert werden, um in den gewünschten Zahlenbereich 0 bis 5 zu kommen. Da Nachkommastellen vom Controller bei der Berechnung abgeschnitten werden, muß eins addiert werden und die Ungleichung "32767 / x < (größte_gewünschte_Zufallszahl + 1)" erfüllt sein. Deshalb muß 32767 durch 6 geteilt werden, was laut Taschenrechner 5461.166667 ist. Damit bei der Division ein Wert kleiner 6 herauskommt, muß der nächsthöhere Wert 5462 genommen werden. Somit werden mit "((RAND SHR 1)+16384)/5462" die gewünschten Zufallszahlen von 0 bis 5 erzeugt. Zur Eingrenzung des Wertebereichs von Zufallszahlen gibt es auch einen Forenbeitrag.

#### RANDOMIZE

##### Beschreibung

Zufallszahlengenerator neu initialisieren.

##### Hinweis

Nach einem Reset läuft der Timer in der OM von Null los. Ein RANDOMIZE TIMER am Programmbeginn ist also nichts anderes als ein RANDOMIZE 0. In diesem Fall würden also nach jedem Reset die gleichen Zufallszahlen generiert. Solange Synchronität zwischen Systemzeit und RANDOMIZE TIMER besteht, wird sich daran nichts ändern.

##### Syntax

`RANDOMIZE x`

##### Beispiel

`RANDOMIZE TIMER`

#### READ

##### Beschreibung

Datei öffnen zum Auslesen von Daten.

##### Syntax

`READ`

##### Beispiel

`OPEN# FOR READ`

#### RETURN

##### Beschreibung

Rückkehr aus einer Subroutine (Unterprogramm) oder einer Funktion. Bei Funktionen läßt sich ein Wert über den sogenannten Rechenstack an den Aufrufer zurückgeben.

##### Syntax

`RETURN
RETURN wert`

##### Beispiel

`RETURN
RETURN 123`

#### RETURN INTERRUPT

##### Beschreibung

Rückkehr aus der BASIC-Interruptroutine. Siehe INTERRUPT-Befehl.

##### Syntax

`RETURN INTERRUPT`

##### Beispiel

`RETURN INTERRUPT`

#### RXD

##### Beschreibung

Test, ob ein Byte seriell empfangen wurde und aus dem Empfangsbuffer gelesen werden kann.
Auf der Open-Macro liefert diese Funktion an der PORT[1]-Schnittstelle immer ON zurück.

##### Syntax

`RXD`

##### Beispiel

`IF RXD THEN GET x`

#### SECOND

##### Beschreibung

Sekunden-Wert der Echtzeituhr.
Auf der OM wird TIMER automatisch auf Null gesetzt, wenn SECOND beschrieben wird.

##### Hinweis

Während des Zugriffs auf die Variablen der Echtzeituhr läuft die interne Uhr weiter. Das muß insbesondere beim Auslesen der Uhrzeit beachtet werden. Es muß zunächst der Sekundenwert in einer Variable zwischengespeichert, dann die übrige Uhrzeit gelesen und anschließend das Auslesen wiederholt werden, falls der zwischengespeicherte Sekundenwert 59 und gleichzeitig der aktuelle Sekundenwert 0 ist. In diesem Fall könnte der Minuten- und sogar der Stundenwert unkorrekt sein.

##### Syntax

`SECOND`

##### Beispiel

`DEFINE mySecond BYTE
DEFINE myMinute BYTE
DEFINE myHour BYTE
REPEAT
mySecond=SECOND 'Uhrzeit auslesen
myMinute=MINUTE
myHour=HOUR
UNTIL mySecond<>59 OR SECOND<>0 'Wiederholen, falls Minute zuende
PRINT myHour;":";myMinute;":";mySecond`

#### SGN

##### Beschreibung

Die mathematische Signum-Funktion. Sie liefert -1 bei negativen und 1 bei positiven Zahlen zurück. Beim Wert Null wird 0 zurückgeliefert.

##### Syntax

`SGN(x)`

##### Beispiel

`z = SGN(x)`

#### SHL

##### Beschreibung

Operator für bitweises arithmetisches Linksschieben. Das zuletzt herausgeschobene Bit wird in der internen Variable Carry zurückgeliefert.

##### Syntax

`SHL`

##### Beispiel

`x = x SHL 3 'entspricht x=x*2^3 oder x=x*8`

#### SHR

##### Beschreibung

Operator für bitweises arithmetisches Rechtsschieben. Das heißt, negative Zahlen bleiben negativ. Das zuletzt herausgeschobene Bit wird in der internen Variable Carry zurückgeliefert.

##### Syntax

`SHR`

##### Beispiel

`x = x SHR 3 'entspricht x=x/2^3 oder x=x/8`

#### SLOWMODE

##### Beschreibung

Der Controller wird in einen stromsparenden Modus versetzt.
Auf der Open-Maxi wird der Bustakt durch SLOWMODE ON wie auf der C-Control 1.1 auf 1/16 (1,25 MHz) reduziert. Dadurch benötigt der Controller nur noch wenige Milliampere Strom. Da die TPM-Module des Controllers angepaßt werden, funktionieren die zeitabhängigen Funktionen BEEP, PAUSE, TIMER, RTC, DA, DCF77, FREQ, usw. wie beim Standardtakt von 20 MHz. Durch SLOWMODE OFF kann wieder auf den Standardtakt zurückgeschaltet werden.
Auf der Open-Macro wird der Parameter ignoriert und ein "STOP"-Befehl ausgeführt, wodurch fast der gesamte Controller stillsteht, bis er durch das Auto-Wakeup-Modul (AWU) aufgeweckt wird. Das geschieht nach ungefähr 16 ms, wobei diese Zeit stark von der Betriebsspannung und der Temperatur abhängig ist. In dieser Zeitspanne benötigt der Controller nur einige wenige µA Strom.

##### Hinweis

Open-Maxi:
Wenn direkt vor dem Ausführen von SLOWMODE ON Daten über die Serielle Schnittstelle gesendet werden, ist es notwendig, einen PAUSE-Befehl vor SLOWMODE ON auszuführen. Sonst werden die letzten Daten mit falscher Baudrate gesendet.
Der Controller arbeitet während SLOWMODE ON mit reduziertem Takt, deshalb darf unter anderem der Hostmode ("End2Host=ON : END") nicht aufgerufen werden, denn er geht von einem Bustakt von 20 MHz aus.
Mit relativ geringem Aufwand sind auch andere Bustakte konfigurierbar.
Open-Macro:
Der Befehl STOP und somit auch SLOWMODE verträgt sich offenbar nicht mit aktivierter KEYB-Pin-Funktionalität und somit aktiver Frequenzmessung (siehe FREQ1): Ist der KEYB-Pin low, wenn STOP ausgeführt wird, fällt der Controller ins Koma und wacht nur nach einem Power-On-Reset (POR) wieder auf.
Das Betriebssystem der OM konfiguriert den Controller so, daß der LVI-Reset im STOP-Mode nicht aktiv ist. Aus diesem Grund funktioniert der Reset-Taster auf dem ersten und zweiten PE-Board während SLOWMODE nicht. Wenn der Controller resettet werden soll kann aber ein Power-On-Reset (POR) durch kurze Wegnahme der Betriebsspannung durchgeführt werden.

##### Syntax

`SLOWMODE ON
SLOWMODE OFF`

##### Beispiel

`' für Open-Maxi:
INCLUDE "omax.def"
SLOWMODE ON ' von 20 MHz auf 1.25 MHz Bustakt umschalten
SCI2BDH=0 ' 9600 Baud bei 1.25 MHz Bustakt
SCI2BDL=8 ' Baudrate = 1.25E6/16/(SCI2BDH*256+SCI2BDL)
WHILE TRUE ' Serielle Schnittstelle im SLOWMODE verwenden
PRINT "Hallo Welt in SLOWMODE!"
PAUSE 25
WEND
' für Open-Macro:
DEFINE taste PORT[2]
WHILE taste ' stromsparend auf einen Tastendruck warten
SLOWMODE ON
WEND
PRINT "Taste gedrueckt!"`

#### SQR

##### Beschreibung

Diese Funktion liefert einen ganzzahligen Näherungswert für die Berechnung der Quadratwurzel.
Auf der OM wird das mathematisch korrekt gerundete Ergebnis zurückgeliefert.

##### Syntax

`SQR(x)`

##### Beispiel

`z = SQR(x)`

#### STEP

##### Beschreibung

Angabe der Schrittweite bei einer FOR-Schleife. Ohne Angabe von STEP wird eine Schrittweite von eins verwendet. Auch negative STEP-Werte sind möglich.
Zu beachten ist, daß die Variable mit dem bei FOR angegebenen Endwert auf Gleichheit verglichen wird. Es ist also durchaus möglich, nie endende Schleifen zu erzeugen.

##### Syntax

`STEP`

##### Beispiel

`FOR a = 1 TO 10 STEP 2 'Das ist eine Endlosschleife, da die Variable
PRINT a 'immer nur ungerade Werte annimmt (1, 3, 5, 7,
NEXT '9, 11, 13, ...), der Endwert aber gerade ist.`

#### SYS

##### Beschreibung

Aufruf einer Maschinensprache-, bzw. Assembler-Routine, die mit dem Befehl "RTS" abgeschlossen werden muß. Optional lassen sich bis zu acht Parameter über den sogenannten Rechenstack an die Assembler-Routine übergeben. Eine vom Anwender per AS05 erstellte Assembler-Routine wird üblicherweise mittels SYSCODE in den BASIC-Quellcode eingebunden. Bei der C-Control 1.1 beginnt dieser SYSCODE-Bereich an Adresse &h101. Bei der Open-Macro an Adresse &hFD00 und bei der Open-Maxi an Adresse &h0900.
Open-Macro:
Der Controller MC908QB8, auf dem die Open-Macro basiert, stammt von Freescale (heute NXP). Auf den Websides zu den 68HC908Q-Mikrocontrollern können neben diversen Application Notes mit Beispielcode auch das Data Sheet zum QB8 heruntergeladen werden. Für Assemblerprogrammierer besonders interessant ist das Central Processor Unit Reference Manual CPU08RM von Freescale, in dem alle Befehle der 6808-CPU detailliert erläutert werden. Auf der offiziellen OM-Infosite gibt es bei den Downloads auch eine Assemblerbeschreibung in deutscher Sprache. Interessante Informationen zum Controller stehen auch im Timer Interface Module Reference Manual TIM08RM. Auf dem deutschen Büchermarkt war vor einiger Zeit das Franzis'-Buch "68HC08-Mikrocontroller erfolgreich anwenden" erhältlich. Das sollte 128,- DM kosten, wurde aber wegen zu vieler Fehler später für wenige Mark verramscht. Auf dem Second-Hand-Markt ist es sicherlich noch immer erhältlich. Es behandelt natürlich nicht die aktuellen 68HC08-Controller.
Open-Maxi:
Die Open-Maxi basiert auf dem HCS08-Mikrocontroller MC9S08AW60 von Freescale. Da die HCS08-CPU abwärtskompatibel zur 6808-CPU ist, kann die gleiche Assemblerbeschreibung wie bei der Open-Macro verwendet werden. Siehe oben. Auch das Reference Manual zur HCS08-Familie ist sehr interessant.

##### Syntax

`SYS adresse
SYS adresse wert1, wert2, wert3`

##### Beispiel

`SYS &H101
SYS &HFD00
a=SYS(&HFD00)`

##### Hinweis

Der SYS-Befehl ist sehr mächtig. Die CPU kann damit veranlaßt werden, an beliebiger Adresse stehenden Maschinencode auszuführen. Der Anwender sollte deshalb vor der Verwendung dieses Befehls genau prüfen, ob an der Zieladresse ein korrektes Maschinenspracheprogramm steht. Ansonsten könnte der Controller abstürzen oder Schaden nehmen. Ein Sprung in nichtimplementierten Speicher wird allerdings abgefangen und bewirkt einen "Illegal Address Reset" und bei der Ausführung von ungültigen Maschinensprachebefehlen wird ein "Illegal Opcode Reset" ausgelöst, woraufhin das Open-Macro-Betriebssystem in den Systemmonitor MON08 verzweigt. Dieser kann über die Serielle Schnittstelle an PORT[1] (gleich PTA0) bedient werden. Auf der Open-Maxi wird der Controller resettet und startet von neuem.

#### SYSCODE

##### Beschreibung

Einbinden einer S19-Datei mit Assembler-Routinen in das BASIC-Programm. Die Assembler-Routinen werden in Form von sogenannten "SYS-Bytes" an den Controller übertragen und in den SYSCODE-Bereich geschrieben.
Beim Dateinamen werden nun auch beliebige Pfade unterstützt. Falls kein Pfad angegeben wird, dann sucht der OCBASIC-Compiler zuerst im Verzeichnis mit dem BASIC-Sourcecode nach der Datei. Ist sie dort nicht zu finden, wird im Compiler-Verzeichnis und schließlich im aktuellen Verzeichnis gesucht.
Um eine S19-Datei zu erzeugen, kann der bekannte AS05-Assembler von Frank A. Vorstenbosch verwendet werden: Der Aufruf "as05 -sl datei.asm" erzeugt die Ausgabedatei "datei.s19".
Die Bezeichnung Assembler-Routine ist nicht ganz korrekt. Genaugenommen handelt es sich um Maschinencode-Routinen.

##### Syntax

`SYSCODE`

##### Beispiel

`SYSCODE "test.s19"`

##### Hinweis

Auf der Open-Macro und Open-Maxi können Assemblerroutinen genauso wie bisher auf der C-Control Version 1.1 per SYSCODE in den BASIC-Sourcecode eingebunden und bei Bedarf per SYS aufgerufen werden. Darüber hinaus ist es möglich, ausgetestete Assemblerroutinen in sogenannte INLINE-Assemblerroutinen und INLINE-Interrupt-Assemblerroutinen umzuwandeln und auf diese Weise platzsparend in ein CCBASIC-Programm einzubinden. OCBASIC besitzt einen integrierten 6808-Assembler und ist deshalb nicht mehr auf SYSCODE angewiesen. Weitere Informationen sind in den Beispielprogrammen zur OM enthalten.

#### SYSEND

##### Beschreibung

Abschluß einer mit SYSCODE direkt eingegebenen Byte-Liste mit Assembler-Routinen.

##### Syntax

`SYSEND`

##### Beispiel

`SYSCODE &H81 SYSEND`

#### TABLE

##### Beschreibung

Definition einer Datentabelle. Die Werte in der Tabelle lassen sich mit den LOOKTAB- und LOOKTABBYTE-Befehlen auslesen. Datentabellen und Programmcode sollten nicht vermischt werden, da dann unter Umständen die Daten in der Tabelle als Programmcode ausgeführt werden. Sicherheitshalber sollten Datentabellen deshalb an das Ende des BASIC-Quellcodes hinter ein END gesetzt werden. Kommata zwischen den Werten in der Tabelle sind optional.
Auf der OM existieren spezielle Tabellenformen, die INLINE-Assemblerprogramme enthalten. Es gibt auch Tabellen mit Tokencode. Nähere Information dazu befindet sich in den Beispielprogrammen.

##### Hinweis

Tabellen enthalten standardmäßig konstante Werte im Wordformat. Wenn Byte-Tabellen angelegt werden sollen, muß das Schlüsselwort BYTE hinter dem Tabellennamen eingefügt werden. Die Daten in der Tabelle belegen dann nur halb soviel Speicher.

##### Syntax

`TABLE tabellenname [BYTE]
TABEND`

##### Beispiel

`TABLE nummer1 'Tabelle im Wordformat
56 77 89
TABEND 'statt "TABEND" ist auch "END TABLE" verwendbar
TABLE nummer2 BYTE 'Tabelle im Byteformat
4,5,"Es werden jetzt auch Strings unterstützt",55,6,"A","B","C"
TABEND
TABLE nummer3 BYTE "datei.tab" 'Tabelle aus Datei lesen`

#### TABEND

##### Beschreibung

Abschluß bei mit TABLE direkt eingegebenen konstanten Werten.

##### Syntax

`TABEND`

##### Beispiel

`TABLE nummer1
17 25 4 5
TABEND`

#### TIMER

##### Beschreibung

Abfrage des Timers. Der Timer wird alle 20 Millisekunden automatisch erhöht (inkrementiert) und nimmt Werte von -32768 bis 32767 an.
Auf der Open-Macro werden während BEEP, SLOWMODE und GET und INPUT bei der PORT[1]-Schnittstelle alle Interrupts deaktiviert und deshalb wird auch der Timer nicht mehr automatisch weitergezählt.
Wenn sich der TIMER zwischen zwei TIMER-Abfragen um eins weiterbewegt hat, sind mehr als 0 ms und weniger als 40 ms vergangen. Im Durchschnitt sind das 20 ms.

##### Syntax

`TIMER`

##### Beispiel

`x = TIMER
' Überlauftolerante Timerabfrage:
DEFINE ende WORD
ende=TIMER+10
PRINT "Soll-Ende: ";ende
REPEAT
PAUSE 1
PRINT TIMER
UNTIL ende-TIMER<=0
PRINT "Ist-Ende: ";TIMER`

#### TOG

##### Beschreibung

Umschalten eines Digitalports. Der Port muß vorher mittels "port = ON" oder "port = OFF" aktiviert werden.
Die Befehle TOG, PULSE und DEACT werden bei den Extended Ports nicht unterstützt.

##### Verfügbarkeit

`Open-Macro: PORT[1], PORT[2], PORT[4], PORT[5], PORT[6] und
PORT[9] bis PORT[16]
Open-Maxi: PORT[1] bis PORT[16] und PORT[33] bis PORT[40] (optional mehr)`

##### Syntax

`TOG`

##### Beispiel

`TOG led`

#### WAIT

##### Beschreibung

Warten auf Eintreten einer Bedingung.

##### Syntax

`WAIT bedingung`

##### Beispiel

`WAIT taste=ON`

#### WORD

##### Beschreibung

Definiert eine vorzeichenbehaftete 16-Bit-Word-Variable. Sie kann Werte von -32768 bis 32767 annehmen. Auf der Open-Macro stehen 70, und auf der Open-Maxi sogar 256 Word-Variablen zur Verfügung.

##### Syntax

`DEFINE bezeichner WORD
DEFINE bezeichner WORD[index]`

##### Beispiel

`DEFINE variable1 WORD
variable1=-12345`

##### Hinweis

Nach Programmstart ohne Fehler wird vom Betriebssystem der gesamte Variablenspeicher mit Ausnahme von VERSION auf 0 gesetzt. Damit alle Variablen auf 0 stehen, sollte der Anwender bei Programmstart VERSION=0 ausführen.

#### WORDPORT

##### Beschreibung

Definiert einen 16-Bit-Digitalport. Somit kann auf die ersten 16 Digitalports der Open-Maxi gleichzeitig zugegriffen werden.

##### Verfügbarkeit

`Open-Macro: WORDPORT[1]
Open-Maxi: WORDPORT[1]`

##### Syntax

`DEFINE bezeichner WORDPORT[1]`

##### Beispiel

`DEFINE alle_ports WORDPORT[1]`

#### WRITE

##### Beschreibung

Datei öffnen zum Schreiben neuer Daten.

##### Syntax

`WRITE`

##### Beispiel

`OPEN# FOR WRITE`

#### XOR

##### Beschreibung

Logische und bitweise Exclusiv-ODER-Verknüpfung, auch Antivalenz genannt.

a | b | a XOR b
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0

Weitere logische Operatoren sind NOT, AND, NAND, OR und NOR.

##### Syntax

`XOR`

##### Beispiel

`x = a XOR b`

#### YEAR

##### Beschreibung

Jahr-Wert der Echtzeituhr.
Die Open-Macro unterstützt standardmäßig keine Datumsfunktion in der Echtzeituhr und die interne Variable YEAR liegt deshalb auf dem gleichen RAM-Speicherplatz wie FREQ1.

##### Syntax

`YEAR`

##### Beispiel

`PRINT YEAR`

### Neue Schlüsselwörter

Der OCBASIC-Compiler unterstützt einige neue Befehle und interne Variablen, die in CCBASIC nicht zur Verfügung stehen. Sie erzeugen Tokencode, der meist nur von der OM ausgeführt werden kann.

#### ADD

##### Beschreibung

Dient zur schnellen und speicherplatzschonenden Addition bei User-Variablen. Das Carry-Flag wird nicht gesetzt.

##### Syntax

`ADD variable,ausdruck`

##### Beispiel

`DEFINE a BYTE
ADD a,1 'entspricht a=a+1`

#### ASC

##### Beschreibung

Der OCBASIC-Dialekt ermöglicht die Verwendung von Stringkonstanten, die mittels ASC()-Funktion in ihren ASCII-Code, also eine Zahl, umgewandelt werden können. Vergleichbar mit Stringkonstanten in Assembler (z.B. #'0' für #48). Dadurch lassen sich ohne Umrechnerei und umfangreiche Konstantendefinitionen komfortabel einzelne ASCII-Zeichen in den Sourcecode einfügen.
Mittels ASC() ausgewertete Stringkonstanten können ein Zeichen (ein Byte) lang sein. Der Compiler unterstützt bei CVI() aber bis zu zwei Zeichen lange Stringkonstanten, die als Word, bzw. Integerzahl, ausgewertet werden. Es wird das auf Motorola-CPUs übliche Big-Endian-Format verwendet.

##### Syntax

`ASC("x")
CVI("xx")`

##### Beispiel

`PUT ASC("?") 'entspricht PUT 63
lcd_writechar ASC("L") 'entspricht lcd_writechar 76
lcd_writechar ASC("C") 'entspricht lcd_writechar 67
lcd_writechar ASC("D") 'entspricht lcd_writechar 68
END
#lcd_writechar
...
RETURN`

#### ASSEMBLER (!)

##### Beschreibung

Im OCBASIC-Compiler ist ein 6808-Assembler integriert. Assemblerbefehle können mit dem !-Kommando komfortabel, ohne externen Assembler, in das Programm eingefügt werden. Diese Assemblerbefehle sollten immer innerhalb einer INLASM-PROCEDURE oder einer INLASM-FUNCTION stehen. Weitere Informationen zur Assemblerprogrammierung stehen bei SYS. Dem OCBASIC-Compiler liegen außerdem etliche Beispielprogramme bei. Zudem gibt es einen Assemblerkurs für die OM-Mikrocontroller: Teil 1, Teil 2, Teil 3 und Teil 4.

##### Syntax

`! assemblerbefehl`

##### Beispiel

`INCLUDE "omac.def" 'auf der Open-Maxi: INCLUDE "omax.def"
DEFINE variable BYTE
variable=5
assembler 'Aufruf der Assemblerroutine
PRINT variable
END
PROCEDURE assembler INLASM
! lda variable 'Lade den Inhalt der Variable in den Akkumulator
! add #123 'Addiere den konstanten Wert 123 zum Akku
! sta variable 'Speichere den Akku-Inhalt in die Variable
! rts 'Rücksprung zum BASIC-Interpreter
END PROCEDURE`

#### CSTKPTR

##### Beschreibung

Mit dieser internen Variable kann der Zeiger (Pointer) des Rechenstacks gelesen oder verändert werden.

##### Syntax

`CSTKPTR`

##### Beispiel

`PRINT CSTKPTR 'liefert auf der OM eine 8-Bit-Adresse im RAM zurück`

#### DBNZ

##### Beschreibung

DBNZ-Schleifen sind eine Alternative zu FOR..NEXT-Schleifen und werden deutlich schneller als diese ausgeführt. Der Zähler in der Schleife ist immer DBNZCTR und belegt auf der OM den gleichen RAM-Speicher wie RAND und ERR. Durch den DBNZ-Befehl wird der Zähler um eins verringert (dekrementiert) und anschließend gesprungen, falls der Zähler ungleich Null ist. ("Decrement and Branch if Not Zero")

##### Syntax

`DBNZ label`

##### Beispiel

`DBNZCTR=15
#loop
PRINT DBNZCTR;" ";
DBNZ loop`

#### DBNZCTR

##### Beschreibung

Diese interne Variable ist der Zähler für DBNZ-Schleifen. Der Schleifenzähler DBNZCTR hat Byte-Format und der Wert 0 entspricht bei DBNZ dem Wert 256.

##### Syntax

`DBNZCTR`

#### DIM

##### Beschreibung

Dieser Befehl kann alternativ statt DEFINE benutzt werden und hat die gleiche Funktion wie dieser. Siehe DEFINE.

##### Syntax

`DIM bezeichner [AS] art [OF variable]`

#### ERR

##### Beschreibung

Sobald ein Fehler auftritt, wird in dieser internen Variable der Fehlergrund als Fehlernummer kodiert abgelegt. Nach Programmstart ohne Fehler enthält ERR den Wert 0. ERR belegt auf der OM den gleichen RAM-Speicher wie DBNZCTR und RAND.

Fehlercode | Erklärung
0 | kein Fehler
1 | Zu viele GOSUB-Verschachtelungen
2 | RETURN ohne GOSUB
3 | File-I/O-Error (nur Open-Macro)
128 | Illegales Token

Siehe dazu auch RunOnErr, ERRADR, PRINT# und Beispiel im Forum.

##### Syntax

`ERR`

##### Beispiel

`RunOnErr=ON
IF ERR THEN
PRINT "FEHLER: ";ERR
END
ELSE
PRINT "keine Fehler!"
END IF
' restliches Programm`

##### Hinweis

Bei Fehlern in der Datendatei (d.h. wenn das I²C-EEPROM nicht ansprechbar ist - kein ACK sendet) wird die Programmausführung auf der Open-Maxi nicht mehr wie auf den bisherigen OM-Controllern mit Fehler abgebrochen, sondern nur das Fehlerbit FileErr gesetzt, das der Anwender abfragen kann. Wenn das Fehlerbit gesetzt ist, werden vom Betriebssystem alle nachfolgenden Dateibefehle (z.B. PRINT#) ignoriert. Das Fehlerbit wird vom Betriebssystem bei OPEN# automatisch resettet.

#### ERRADR

##### Beschreibung

Mit Hilfe dieser Word-Variable läßt sich die Stelle ermitteln, an der ein Fehler auftrat. Es wird die Adresse aus dem Programmzähler (BASIC-PC) nach Auftreten des Fehlers zurückgeliefert, deshalb steht in ERRADR die Adresse des ersten Bytes hinter dem fehlerhaften Tokenbefehl. ERRADR belegt auf der OM den gleichen RAM-Speicher, der zur Speicherung der Adresse der BASIC-Interruptroutine verwendet wird (siehe INTERRUPT).
Siehe dazu auch RunOnErr, ERR, PRINT# und Beispiel im Forum.

##### Syntax

`ERRADR`

##### Beispiel

`RunOnErr=ON
IF ERR THEN
PrintHex=ON
PRINT "Fehleradresse: $";ERRADR 'oder ERRADR-UPROGBASE
End2Host=ON
END
END IF
' restliches Programm`

#### FILEPOS

##### Beschreibung

Welche Adresse per INPUT# ausgelesen und mit PRINT# beschrieben wird, legt der Dateipositions-Zeiger FILEPOS im RAM fest. Außerdem existiert ein Dateiende-Zeiger FILEEND im Flash- oder EEPROM-Speicher, der bei CLOSE# aktualisiert wird, falls die Datei verändert wurde.

##### Syntax

`FILEPOS`

##### Beispiel

`' für Open-Macro:
DEFINE a BYTE
FILEPOS=&he8c2 'Das Anwender-Programm beginnt an Adresse &he8c2
FOR a=0 TO 255 'Die ersten 256 Bytes des Programms ausgeben
PRINT INPUT#;" ";
NEXT a`

#### FREERAM

##### Beschreibung

Einige Bytes im RAM-Speicher wurden freigehalten, damit Assemblerprogramme ihre Daten speichern können. Der Speicher läßt sich auch gut zur Parameterübergabe an Assembler-Interruptroutinen verwenden und die ersten 5 Bytes können in BASIC und Assembler über die internen Variablen FREERAM1 bis FREERAM5 angesprochen werden. Im Adreßraum des Controllers entspricht das dem RAM-Speicher ab Adresse $7b (Open-Macro), bzw. $80 (Open-Maxi).
Auf der Open-Macro befindet sich hinter dem FREERAM-Bereich das USER-RAM, das die Variablen aufnimmt.
Auf der Open-Maxi befinden sich hinter dem FREERAM-Bereich sieben Bytes zum Zwischenspeichern der Systemzeit. Durch Setzen von ClockDis kann das Weiterzählen der Uhr deaktiviert werden. Dann lassen sich die Bytes als Variablen nutzen.
Assemblerroutinen wird vom Betriebssystem automatisch im X-Register die Adresse von FREERAM1 übergeben. Daten lassen sich also schnell z.B. per "STA ,x" ablegen und mit "LDA ,x" bis "LDA 4,x" lesen.

##### Hinweis

Die interne Variable FREERAM1 enthält nach Programmstart den Wert aus dem "SIM Reset Status Register" (SRSR) oder 13, falls das Programm durch Drücken von RETURN im Hostmode gestartet wurde. Start nach END wird durch den Wert 255 signalisiert. FREERAM1 wird außerdem vom Betriebssystem zur Parameterübergabe an einige IIARs benutzt. Siehe URIllTok und URTok. Es sollte daher nicht in Assembler-Interruptroutinen verwendet werden.

##### Syntax

`FREERAM
FREERAM1
FREERAM2
FREERAM3
FREERAM4
FREERAM5`

##### Beispiel

`FREERAM=123 'entspricht FREERAM1=123
DEFINE datenbyte FREERAM2 'alternativer Name für FREERAM2
datenbyte=24`

#### FUNCTION

##### Beschreibung

Der Anwender kann eigene Funktionen definieren, die im Programm genauso wie die Standardfunktionen (z.B. "a=SQR(x)") benutzbar sind. Funktionen sind eine Sonderform von Unterprogrammen (Subroutinen). Im Gegensatz zu den Unterprogrammen ist die Rückgabe eines numerischen Wertes oder einer Stringkonstante möglich.
Im Programm werden Funktionen durch ihren Namen aufgerufen. Hinter dem Namen kann eine Liste von Übergabeparametern angegeben werden. Diese Liste sollte in Klammern eingeschlossen werden. Der Rückgabewert der Funktion kann einer Variablen zugewiesen, über die Serielle Schnittstelle ausgegeben, als Parameter einer Funktion oder eines Befehls verwendet werden, etc.
Das FUNCTION-Kommando erzeugt ein Sprungziel (Label), das den Namen der Funktion trägt, danach folgen die Anweisungen zum Holen der Übergabeparameter vom Stack, dann folgt der Funktions-Körper mit den Anweisungen und schließlich wird die Funktion mit einem RETURN verlassen, das zugleich den Rückgabewert der Funktion auf dem Rechenstack ablegt. Das FUNCTION-Schlüsselwort kann zu FUNC verkürzt werden.
Innerhalb einer Funktion besteht vollkommen freier Zugriff auf alle Variablen des Hauptprogramms. Anders als in anderen BASIC-Dialekten können keine lokalen Variablen definiert werden, die nur innerhalb der Funktion Gültigkeit besitzen.

##### Syntax

`FUNCTION funktionsname1 (parameterliste)
anweisungen
RETURN ausdruck
END FUNCTION
FUNCTION funktionsname2 (parameterliste)
anweisungen
RETURN ausdruck`

##### Beispiel

`DEFINE a,b,c BYTE
PRINT funktion(81,64) 'User-Funktion aufrufen und Parameter übergeben
c=funktion(81,64) 'Rückgabewert in einer Variable speichern
funktion 81,64 'Funktion aufrufen und Rückgabe ignorieren
PRINT LOOKTAB(tabelle1,5) 'das sechste Byte aus der Tabelle
PRINT SYS(&h101 1,2,3) 'Assemblerprogramm als Funktion aufrufen
PRINT INPUT# 'aus der Datei lesen
PRINT GET+INPUT 'von der Seriellen Schnittstelle lesen
END
' Eine Funktion mit zwei Parametern und Rueckgabewert
FUNCTION funktion(a,b) 'a und b werden mittels Stack uebergeben.
PRINT "funktion"
RETURN SQR(a)+SQR(b) 'Das RETURN pusht einen Wert auf den Stack.
' Eine Tabelle im Byteformat
TABLE tabelle1 BYTE 'Natürlich wird auch die alte Syntax unter-
1,2,3,4,5,6,7 'stützt. Tabellen enthalten standardmäßig
END TABLE 'nach wie vor Words, keine Bytes.`

##### Hinweis

Der OCBASIC-Compiler überprüft nicht die korrekte Vorgehensweise bei der Übergabe und dem Holen der Parameter mittels Rechenstack. Es fällt in den Aufgabenbereich des Anwenders, darauf zu achten, daß die Anzahl der Parameter übereinstimmt. Andernfalls kommt es zu Stackfehlern, die aber wegen des besonderen Stackhandlings der C-Control normalerweise keine Schwierigkeiten verursachen. Stackfehler sind nur in zwei Fällen kritisch: Wenn innerhalb einer BASIC-Interruptroutine bei aktiviertem RealPop Stackfehler auftreten, führt das zu Fehlern bei Berechnungen und Zuweisungen im Hauptprogramm. Außerdem können bei deaktiviertem RealPop Stackfehler kritisch sein, welche durch Funktionen auftreten, die in einem Ausdruck wie "b+funktion" verwendet werden. Das "b" wird vor dem Funktionsaufruf auf den Rechenstack gelegt und geht durch Stackfehler, die innerhalb der Funktion auftreten, verloren. Die anschließende Addition liefert somit ein falsches Ergebnis. Durch Umstellung der Berechnung zu "funktion+b" läßt sich das Problem beheben. Ein weiterer Vorteil dieser Umformung ist, daß nun in der Funktion der gesamte Rechenstack zur Verfügung steht. Wenn mehr als eine Anwenderfunktion in einem Ausdruck verwendet werden soll, sollten die Funktionen einzeln aufgerufen und deren Rückgabewert zunächst in Variablen zwischengespeichert werden.

#### GSTKPTR

##### Beschreibung

Mit dieser internen Variable kann der Zeiger (Pointer) des GOSUB-Stacks gelesen oder verändert werden. Das läßt sich zum Beispiel zur Realisierung von EXIT FAR verwenden. Siehe Beispiel.

##### Syntax

`GSTKPTR`

##### Beispiel

`' EXIT FAR demonstrieren
DIM exitfarptr BYTE
exitfarptr=GSTKPTR
erstesub
#exitfar
PRINT "Programmende"
END
PROCEDURE erstesub
zweitesub
PRINT "wird niemals ausgefuehrt"
RETURN
END PROCEDURE
PROCEDURE zweitesub
drittesub
PRINT "wird niemals ausgefuehrt"
RETURN
END PROCEDURE
PROCEDURE drittesub
PRINT "Fehler in einer Subroutine"
PRINT "Springe direkt zurueck"
GSTKPTR=exitfarptr
GOTO exitfar
RETURN
END PROCEDURE`

#### I2C-LCD

##### Beschreibung

Die Open-Maxi unterstützt das komfortable Ansprechen von I²C-LCDs. Dazu muß ein normales Text-LCD (HD44780-kompatibel, Industriestandard) an einen I²C-Portexpander PCF8574 angeschlossen und der Portexpander mit dem I²C-Bus der Open-Maxi verbunden werden. Die I²C-Adresse des Portexpanders PCF8574 ist änderbar. Dadurch wird das Ansprechen mehrerer LCDs ermöglicht. Außerdem kann so auch ein PCF8574A verwendet werden. Die Hintergrundbeleuchtung oder die von einigen LCDs verwendete 2. Enable-Leitung lassen sich vom Anwender setzen.

##### Syntax

`LCDINIT 'LCD initialisieren
LCDCLS 'Bildschirm vom LCD löschen
LCDLOCATE zeile,spalte 'Cursor im LCD positionieren
LCDCMD kommando 'Kommando zum LCD schicken
LCDPUT zeichen 'Zeichen auf dem LCD darstellen
LCDPRINT string oder zahl 'String oder Zahl auf dem LCD darstellen`

##### Beispiel

`INCLUDE "omax.def"
DIM w WORD 'eine 16-Bit-Wordvariable
PrintSpc=ON 'SPACE vor einem dezimalen PRINT
' I²C-Adresse vom PCF8574 für das I²C-LCD und I²C-Bustakt setzen:
POKE i2clcdadr,&h40 'Das sind die Defaultwerte
POKE i2cdelay,20 ' nach Programmstart
' I²C-LCD ansprechen, initialisieren und Demotext ausgeben:
PAUSE 2 'Vorgeschriebene Verzögerung für das LCD
LcdLight=ON 'Die Hintergrundbeleuchtung könnte invertiert sein
LCDINIT 'Setzt LcdErr auf OFF bei ACK vom PCF8574,
IF LcdErr THEN ' sonst auf ON
PRINT "NoAck vom I2C-LCD"
END
END IF
LCDCLS 'Löscht den Bildschirm
LCDCMD &b00001111 '"Display on", "Cursor on" & "Blinking on"
LCDLOCATE 0,0 'Position im 4*20-LCD
LCDPRINT "Zahl:";-12345
LCDLOCATE 1,0
w=-32768
LCDPRINT "Variable:";w
LCDPUT ASC("!")
END`

##### Hinweis

Zum Testen der I²C-LCD-Funktionen wurde das 4-zeilige "LCD 204B LED" von Reichelt benutzt, das auf der Controllertype KS0076B basiert. Außerdem wurde das I²C-LCD von Conrad Electronic verwendet. Andere Text-LCDs, die nicht kompatibel sind, könnten Probleme machen. Von den I²C-LCD-Funktionen wird die gleiche Pinbelegung wie die des I²C-LCDs von Conrad Electronic vorausgesetzt, das auf Seite 15 der PDF-Datei C-Control I Erweiterungsmodule für den I²C-Bus beschrieben ist. Die Verbindung zwischen LCD und Portexpander ist im Folgenden aufgelistet:

    PCF8574 | LCD
    ----------------------------------------------------------------------
    P0  4   | DB4 11 \
    P1  5   | DB5 12  \ die oberen 4 Bits
    P2  6   | DB6 13  / vom 8-Bit-Datenbus
    P3  7   | DB7 14 /
    P4  9   | R/W  5 -- Lesen (1) oder Schreiben (0)
    P5 10   | RS   4 -- Daten (1) oder Instruktion (0) übermitteln
    P6 11   | EN   6 -- Daten bei fallender Flanke (1 nach 0) übernehmen
    P7 12   | EN2    -- Hintergrundbeleuchtung (oder 2. Enable-Leitung)

#### INCLUDE

##### Beschreibung

Mit diesem Befehl wird der Compiler angewiesen, eine andere Datei an die aktuelle Position des Sourcecodes einzufügen. Bei der 16-Bit-Version von OCBASIC muß der Pfad und Name der Datei DOS-Konventionen genügen. Der Name darf also maximal 8 Zeichen plus Punkt und Endung enthalten. Bei Dateien mit längerem Namen muß der von Windows bereitgestellte kurze DOS-Name verwendet werden.
Wird kein Pfad angegeben, sucht der Compiler nach der Datei zunächst im Verzeichnis, in dem der BASIC-Sourcecode steht. Falls er dort nicht fündig wird, sucht er im Verzeichnis, in dem sich der Compiler OCBAS.EXE befindet. Falls die Datei auch dort nicht vorhanden ist, wird das aktuelle Verzeichnis ("current directory") benutzt und gegebenenfalls ein Fehler gemeldet.
Die Endungen der INCLUDE-Dateien wurden mit Bedacht gewählt. Die Endung DEF signalisiert dem Anwender, daß diese Datei nur Definitionen (also keine BASIC-Befehle oder Tabellen) enthält und deshalb mittels INCLUDE am Beginn seines Sourcecodes eingefügt werden sollte. Dateien mit der Endung IIA enthalten Systemerweiterungen, die vom Anwender direkt hinter die Definitionen, vor den ersten Befehl seines Programms, gestellt werden müssen. Die Endung PRO signalisiert, daß in der Datei BASIC- oder Assembler-Unterprogramme stehen. Sie darf vom Anwender deshalb nicht an den Beginn seines Sourcecodes gestellt werden.

##### Syntax

`INCLUDE dateiname`

##### Beispiel

`INCLUDE "omac.def" 'auf der Open-Maxi: INCLUDE "omax.def"
' restliche Definitionen
INCLUDE "extports.iia" '1. Systemerweiterung einbinden
INCLUDE "omidesci.iia" '2. Systemerweiterung einbinden
#main
' Hauptprogramm
END
INCLUDE "om_i2c.pro" 'Hilfsroutinen
INCLUDE "om_fw.pro"`

#### INLINE

##### Beschreibung

Mit diesem Befehl wird der Compiler angewiesen, Daten an die aktuelle Position der Ausgabedatei einzufügen.
Der Befehl muß mit Bedacht verwendet werden. Es besteht die Gefahr, daß die Daten als Tokencode ausgeführt werden und somit die OM abstürzen lassen.

##### Syntax

`INLINE byteliste`

##### Beispiel

`'Text auf dem LCD ausgeben
SYS lcd_string : INLINE "Pizza-Uhr von D.H.",0`

#### IVAR

##### Beschreibung

Mit diesem Schlüsselwort lassen sich neue interne Variablen definieren. Sinn macht das natürlich nur, wenn diese auch vom Controller unterstützt werden. Für "index" wird die auf der C-Control übliche Zählweise benutzt, die bei 1 beginnt. Dagegen ist im Tokencode der niedrigste Index-Wert 0.

##### Syntax

`DEFINE bezeichner IVAR[index]`

##### Beispiel

`' für Open-Macro:
DEFINE PULLUPA IVAR[140] ' Register für interne Pull-Up-Widerstaende an
' PORTA (liegt im Speicher an Adresse $0b)
PRINT PULLUPA
PULLUPA=0`

#### OPTION

##### Beschreibung

Mit dieser Anweisung wird der OCBASIC-Compiler konfiguriert. Beispielsweise kann der Compiler durch "OPTION CCBAS" veranlaßt werden, von sich aus keine neuen Tokenbefehle der OM zu verwenden, d.h. das Programm ist auf der Original-C-Control Version 1.1 lauffähig, sofern der Anwender keine neuen Befehle (z.B. DBNZ, ADD, SUB, REMOVETOS), Zeiger oder neue interne Variablen benutzt. Diese Option sorgt dafür, daß der Compiler fast den gleichen Code erstellt wie der CCBASIC-Compiler. Das Programm sollte somit auch auf der C-Control 1.2, 2.0, der Conrad-Micro und der B-Control funktionieren, soweit diese Controller kompatibel zur 1.1er und zu CCBASIC sind.

##### Syntax

`OPTION option`

##### Beispiel

`OPTION ccbas
OPTION openmicro
OPTION openmini
OPTION openmidi
OPTION openmacro
OPTION openmaxi`

#### PCADR

##### Beschreibung

Mit Hilfe dieser Word-Variable läßt sich der Programmzähler (Programmcounter, PC) im tokensierten BASIC-Programm auslesen. Auf der OM enthält PCADR eine Adresse im Speicherraum des Controllers, nicht im virtuellen Speicherraum.

##### Syntax

`PCADR`

##### Beispiel

`PRINT PCADR`

#### PEEK & POKE

##### Beschreibung

Mit den Funktionen PEEK und PEEKW können Bytes und Words aus dem Speicher der Open-Maxi gelesen und mit den Befehlen POKE und POKEW in deren Speicher geschrieben werden.

##### Syntax

`PEEK(adresse) 'Ein Byte aus dem Speicher lesen
PEEKW(adresse) 'Ein Word aus dem Speicher lesen
POKE adresse,wert 'Ein Byte in den Speicher schreiben
POKEW adresse,wert 'Ein Word in den Speicher schreiben`

##### Beispiel

`INCLUDE "omax.def"
PRINT PEEK(i2cdelay)
PRINT PEEKW(ufileend)
POKE i2clcdadr,&h40
POKEW freq1tmp,1
DEFINE meinbuffer &h02aa '1. Adresse hinter dem 512 Byte großen USER-RAM
DIM a BYTE
FOR a=0 TO 255
POKE meinbuffer+a,ASC("!")
NEXT a
FOR a=0 TO 255
PUT PEEK(meinbuffer+a)
NEXT a`

##### Hinweis

PEEK, PEEKW, POKE und POKEW müssen mit Bedacht verwendet werden, denn sie sind sehr mächtig. Mit ihrer Hilfe kann jede Speicherzelle im Controller gelesen und beschrieben werden. Außerdem ist zu beachten, daß mit POKEW w,0 nicht etwa die Variable w auf Null gesetzt wird, sondern in w steht die Adresse, auf die geschrieben wird. So ist es auch nicht möglich, mittels POKE PTAD,0 in das Datenregister von Port A zu schreiben, denn PTAD ist eine interne Variable, die in der Definitionsdatei zur Open-Maxi vereinbart ist. Es muß PTAD=0 verwendet werden. PEEK, PEEKW, POKE und POKEW nutzen absolute Adressen im Adreßraum des Controllers, weshalb auch ein POKEW ^w,0 nicht das gewünschte Ergebnis liefert. Denn "^" ist der Adreß-Operator für Zeiger im USER-RAM.

#### POP

##### Beschreibung

Diese Funktion dient dazu, den "Top-Of-Stack" (TOS) des Rechenstacks auszulesen. Auf der OM kann der TOS genauso wie auf der Original-C-Control beliebig oft gelesen und bei Bedarf mittels REMOVETOS vom Stack entfernt werden. POP und REMOVETOS können zum Beispiel benutzt werden, um an Subroutinen oder Funktionen mittels Rechenstack übergebene Parameter vom Stack zu holen. Damit lassen sich auch Funktionen realisieren, die mehr als einen Wert zurückliefern. Siehe auch PUSH.

##### Syntax

`POP`

##### Beispiel

`DEFINE a BYTE
PUSH 123
POP a 'auch a=POP ist möglich`

#### PROCEDURE

##### Beschreibung

Der Anwender kann eigene Unterprogramme (Subroutinen, Prozeduren) definieren, die im Programm genauso wie die Standardbefehle (z.B. "PRINT a") benutzbar sind. Unterprogramme werden hauptsächlich dazu verwendet, um einerseits komplexe Programme in überschaubare Teileinheiten zu zerlegen, und um andererseits mehrfach benötigte Programmteile von unterschiedlichen Orten des Programms zu verwenden. Eine Sonderform der Unterprogramme sind Funktionen. Sie können einen Wert zurückliefern.
Im Programm werden Unterprogramme üblicherweise mittels GOSUB aufgerufen. In OCBASIC ist aber auch der Aufruf durch ihren Namen möglich. Hinter dem Namen kann durch Komma getrennt eine Liste von Übergabeparametern angegeben werden. Diese Liste sollte in Klammern eingeschlossen werden.
Das PROCEDURE-Kommando erzeugt ein Sprungziel (Label), das den Namen des Unterprogramms trägt, danach folgen die Anweisungen zum Holen der Übergabeparameter vom Stack, dann folgt der Prozedur-Körper mit den Anweisungen und schließlich wird das Unterprogramm mit einem RETURN verlassen. Das PROCEDURE-Schlüsselwort kann zu PROC verkürzt werden.
Innerhalb eines Unterprogramms besteht vollkommen freier Zugriff auf alle Variablen des Hauptprogramms. Anders als in anderen BASIC-Dialekten können keine lokalen Variablen definiert werden, die nur innerhalb des Unterprogramms Gültigkeit besitzen.

##### Syntax

`PROCEDURE subroutine1 (parameterliste)
anweisungen
RETURN
END PROCEDURE
PROCEDURE subroutine2 (parameterliste)
anweisungen
RETURN`

##### Beispiel

`DEFINE a BYTE
subroutine 123 'Aufruf einer Subroutine mit Parameteruebergabe
'(entspricht GOSUB, nicht GOTO wie in CCBASIC)
END
' Eine Subroutine mit nur einem Parameter
PROCEDURE subroutine(a)
PRINT "Der Subroutine wurde der Wert ";a;" uebergeben."
RETURN`

##### Hinweis

Der OCBASIC-Compiler überprüft nicht die korrekte Vorgehensweise bei der Übergabe und dem Holen der Parameter mittels Rechenstack. Es fällt in den Aufgabenbereich des Anwenders, darauf zu achten, daß die Anzahl der Parameter übereinstimmt. Andernfalls kommt es zu Stackfehlern, die aber wegen des besonderen Stackhandlings der C-Control normalerweise keine Schwierigkeiten verursachen.

#### PUSH

##### Beschreibung

Dieser Befehl dient dazu, einen Wert auf dem Rechenstack abzulegen. Dieser Wert kann anschließend als "Top-Of-Stack" (TOS) des Rechenstacks per POP ausgelesen werden. Auf der OM kann der TOS beliebig oft gelesen und bei Bedarf mittels REMOVETOS vom Stack entfernt werden. PUSH kann zum Beispiel benutzt werden, um Parameter an Subroutinen oder Funktionen mittels Rechenstack zu übergeben.

##### Syntax

`PUSH ausdruck`

##### Beispiel

`DEFINE a BYTE
PUSH 123 'diese beiden Befehle entsprechen
a=POP 'exakt einem "a=123"`

##### Hinweis

In CCBASIC auf der C-Control 1.1 war es bisher möglich, Assemblermodule per "SYS &H101" aufzurufen. Wie in der Hilfe zu CCBASIC beschrieben, konnte man diesen Assemblermodulen beim Aufruf auch ein paar Parameter, also Daten, übergeben. Zum Beispiel werden bei "SYS &H101 2,3,4" nacheinander die Zahlen 2, dann 3 und schließlich 4 auf den sogenannten Rechenstack (deutsch: Rechenstapel) gePUSHt (geschoben). Im Assemblermodul kann man die Daten vom Stack holen, wozu im Normalfall die Funktion POP benutzt wird.
Einen Stack kann man sich üblicherweise so vorstellen, wie mehrere übereinandergestapelte Teller. Auf den Teller "2" wird der Teller "3" gelegt, auf den wiederum der Teller "4" gestellt wird. Möchte man nun Teller vom Stapel holen, muß man zuerst Teller "4" und anschließend Teller "3" entfernen, bevor man schließlich an den Teller "2" kommt. Mehrere Teller gleichzeitig vom Stapel zu holen ist üblicherweise nicht möglich. Es ist also so, daß der Teller, der zuletzt auf den Stapel gelegt wurde, zwangsläufig als erster Teller vom Stapel geholt werden muß. Es handelt sich also um einen sogenannten LIFO-Stapel ("Last In - First Out", "zuletzt hinein - zuerst hinaus"). Für andere Aufgabengebiete sind auch andere Stapel-Funktionsweisen denkbar.
Auf der C-Control 1.1 arbeitet der Stack nicht exakt nach diesem LIFO-Prinzip. Es lassen sich zwar beliebig viele Werte auf dem Stapel ablegen, sie werden jedoch beim Lesen nicht vom Stapelspeicher entfernt. (Von einer Ausnahme abgesehen.) Gelesen wird vielmehr immer der zuletzt auf den Stack geschriebene Wert TOS ("Top Of Stack", "Spitze des Stapels"). Bei der C-Control 1.1 gehen ältere Einträge verloren, wenn mehr als 7 Einträge auf dem Stack gespeichert werden. Es gibt übrigens noch einen zweiten Stack auf der C-Control: Nämlich den GOSUB-Stack. Auf ihm werden bei einem GOSUB die Rücksprungadresse gespeichert, die bei einem RETURN vom Stack gelesen wird. Dieser Stack arbeitet im Gegensatz zum Rechenstack exakt nach dem oben angesprochenen LIFO-Prinzip.
Der Rechenstack kann in OCBASIC nicht nur wie bisher in CCBASIC bei SYS, sondern auch beim Aufruf von Subroutinen oder Funktionen zur Parameterübergabe benutzt werden. Bei "hallo 1,2,3" werden "1", dann "2" und schließlich "3" auf den Rechenstack gelegt und anschließend ein "GOSUB hallo" ausgeführt. Was in der Subroutine "hallo" mit den Daten geschieht ist nebensächlich. Selbst wenn sie nicht vom Stack gelesen werden führt das im Normalfall zu keinen Fehlern. (Ausnahme: Bei aktiviertem RealPop muß der Rechenstack innerhalb von BASIC-IRQ-Routinen korrekt aufgeräumt werden.)
Mit der Übergabe über den Rechenstack kann man oft Programm- und auch Variablenspeicher sparen. Werden die Parameter an die Subroutine wie bisher auf der C-Control üblich per Variablen an die Subroutine übergeben, also z.B. "a=1 : b=2 : b=3 : GOSUB hallo", dann führt das im Normalfall abgesehen von der geringeren Übersichtlichkeit zu längeren Programmen, da bei jedem Aufruf ein "PUSH 1 : POP a : PUSH 2 : POP b : PUSH 3 : POP c : GOSUB hallo" kodiert werden muß. Bei der Übergabe über den Stack wird hingegen "PUSH 1 : PUSH 2 : PUSH 3 : GOSUB hallo" kodiert, d.h. das POP wird in der Subroutine durchgeführt. Falls die Subroutine "hallo" nur einmal benutzt wird ergibt sich aber natürlich kein Größengewinn.

#### REMOVETOS

##### Beschreibung

Dieser Befehl dient dazu, den "Top-Of-Stack" (TOS) des Rechenstacks vom Stack zu entfernen. Auf der OM kann der TOS beliebig oft gelesen und bei Bedarf mittels REMOVETOS vom Stack entfernt werden. POP und REMOVETOS können zum Beispiel benutzt werden, um an Subroutinen oder Funktionen mittels Rechenstack übergebene Parameter vom Stack zu holen.
Falls das richtige Stackhandling per RealPop aktiviert wurde, dann kann der Befehl REMOVETOS entfallen. Wird er trotzdem benutzt, hat das keine negativen Auswirkungen, da er ignoriert wird.

##### Syntax

`REMOVETOS`

##### Beispiel

`DEFINE a,b BYTE
a=POP
REMOVETOS
b=POP`

#### REPEAT UNTIL

##### Beschreibung

Mit REPEAT..UNTIL kann eine fußgesteuerte Schleife realisiert werden. Sie entspricht der DO..LOOP..UNTIL-Schleife aus anderen BASIC-Dialekten. Die Befehle in der Schleife werden wenigstens einmal durchlaufen, unabhängig davon, ob die bei UNTIL angegeben Bedingung erfüllt (wahr) oder nicht erfüllt (unwahr) ist. Die Bedingung bei UNTIL muß unwahr (also gleich Null) sein, damit die Schleife erneut durchlaufen wird. Es handelt sich somit um die Abbruchbedingung.

##### Syntax

`REPEAT
...
UNTIL bedingung`

##### Beispiel

`DEFINE a BYTE
a=65
REPEAT
PUT a 'alle Zeichen von 65 bis einschließlich 90 ausgeben
a=a+1
UNTIL a>90 'wiederhole, bis a größer 90 ist
PRINT a 'a ist nun 91`

#### SUB

##### Beschreibung

Dient zur schnellen und speicherplatzschonenden Subtraktion bei User-Variablen. Das Carry-Flag wird nicht gesetzt.

##### Syntax

`SUB variable,ausdruck`

##### Beispiel

`DEFINE a BYTE
SUB a,1 'entspricht a=a-1`

#### WHILE WEND

##### Beschreibung

Die WHILE..WEND-Schleife ist kopfgesteuert und die Bedingung bei WHILE muß erfüllt (wahr, das heißt ungleich Null) sein, damit die Schleife durchlaufen wird, sonst wird hinter WEND weitergemacht. Nach jedem Schleifendurchlauf wird die Bedingung erneut überprüft und die Schleife gegebenenfalls verlassen.
Wird als Bedingung "TRUE" oder "ON" angegeben, optimiert der OCBASIC-Compiler die Schleife zu einem einfachen GOTO.

##### Syntax

`WHILE bedingung
...
WEND`

##### Beispiel

`DEFINE i BYTE
i=0
WHILE i<10 'führe die Schleife aus, solange i kleiner als 10 ist
PUT i+48 'Zeichen 48 bis einschließlich 57 ausgeben
i=i+1
WEND
PRINT i 'i ist 10`

#### ZEIGER (^, @)

##### Beschreibung

Zeiger sind vor allem aus der Programmiersprache C bekannt. Sie existieren aber auch in neueren BASIC-Dialekten. Im Prinzip sind Zeiger gewöhnliche Variablen, deren Inhalt die Adresse einer anderen Variable ist. Mit Hilfe von Zeigern ist es auf der OM möglich, Feldfunktionen (Arrays), Stapel, Strukturen, Listen und sogar lokale Variablen zu realisieren. Beispielsweise können Daten im RAM-Speicher auf fortlaufenden Adressen abgelegt werden.

##### Syntax

`DEFINE ^bezeichner BYTE 'Zeiger auf ein Byte im USER-RAM definieren
DEFINE ^bezeichner WORD 'Zeiger auf ein Word im USER-RAM definieren
^bezeichner 'Adreß-Operator (in C ist das "&")
@bezeichner 'Derefenzierungsoperator (in C ist das "*")`

##### Beispiel

`DEFINE ^pb BYTE 'Zeiger auf ein Byte im USER-RAM und
DEFINE d BYTE 'eine normale Variable definieren
d=123 'Wert in der Variable d speichern
PRINT "Die Variable d liegt im USER-RAM an Adresse: ";^d
PRINT "Und hat den Wert: ";d
pb=^d 'Zeiger mit Adresse von d laden
PRINT "Der Zeiger enthaelt als 'Wert' eine Adresse: ";pb
PRINT "Der Wert von d, gelesen mittels Zeiger: ";@pb
@pb=234 'Byte an der Stelle aendern, auf die pb zeigt
PRINT "Nun enthaelt d den Wert: ";d
FOR pb=0 TO 127 'In der Schleife werden die ersten 128 Byte
PRINT @pb;" "; ' des User-RAMs ausgegeben.
NEXT pb`

### Neue interne Variablen

Die OM besitzt zusätzlich viele neue interne Variablen, die größtenteils als Flags, also als Bitvariablen, ausgelegt sind und mit denen sich das Betriebssystem konfigurieren läßt. Außerdem kann auf Systembereiche zugegriffen werden. Wenn die neuen internen Variablen verwendet werden sollen, müssen sie zunächst definiert werden, denn sie sind nicht Bestandteil der OCBASIC-Syntax. Am einfachsten geht das mit Hilfe einer zum verwendeten Controller passenden Definitionsdatei, die auf der offiziellen Informationssite zur OM heruntergeladen werden kann. Sie wird mit dem folgenden INCLUDE-Befehl in das Anwenderprogramm eingebunden. Dieser INCLUDE-Befehl sollte am Beginn jedes Programms stehen.

##### Beispiel

`INCLUDE "omac.def" 'auf der Open-Maxi: INCLUDE "omax.def"`

##### Hinweis

In CCBASIC lassen sich die meisten neuen Variablen nicht so ohne weiteres nutzen, da keine IVAR-Variablen definiert werden können. Insbesondere auf die internen Bit-Variablen müßte über BYTE-Variablen und entsprechende Bitmasken zugegriffen werden.

#### CARRY

##### Beschreibung

Diese interne Bitvariable liefert das Carry nach Berechnungen zurück.

##### Beispiel

`DEFINE a WORD
a=&h8000 SHL 1
PRINT Carry`

#### CLOCKDIS

##### Beschreibung

Mit diesem Bit läßt sich das Weiterzählen der Uhr deaktivieren. Die internen Variablen der Echtzeituhr (HOUR, MINUTE, SECOND, etc.) lassen sich dann frei verwenden.

##### Beispiel

`ClockDis=ON`

#### CONFIG1

##### Beschreibung

Existiert nur auf der Open-Macro.
Eines der beiden Konfigurationsregister vom Mikrocontroller. Sie lassen sich nach jedem Reset nur einmal beschreiben ("write once").
Das Register CONFIG1 wurde bereits vom Betriebssystem beschrieben und erneutes Beschreiben wird daher vom Controller ignoriert.

##### Beispiel

`PRINT CONFIG1`

#### CONFIG2

##### Beschreibung

Existiert nur auf der Open-Macro.
Eines der beiden Konfigurationsregister vom Mikrocontroller. Sie lassen sich nach jedem Reset nur einmal beschreiben ("write once").
Dieses Register kann zur Aktivierung des IRQ- und RST-Pins und zum Wechseln der Taktquelle des ESCI verwendet werden. Nach Reset sind alle Bits gelöscht, das Register enthält also nur 0-Bits.

Bitnummer | Bitname | Beschreibung
0 | RSTEN | RST Pin Function Selection
1 | OSCENINSTOP | Oscillator Enable in Stop Mode
2 | ESCIBDSRC | ESCI Baud Rate Clock Source
3 | reserviert | ---
4 | reserviert | ---
5 | reserviert | ---
6 | IRQEN | IRQ Pin Function Selection Bit
7 | IRQPUD | IRQ Pin Pullup Control Bit, 1=deaktivieren

##### Beispiel

`CONFIG2=&b01000000 'IRQEN im CONFIG2-Register des Controllers setzen`

#### CONONERR

##### Beschreibung

Dieses Bit existiert auf der Open-Macro und Open-Maxi nicht mehr, denn mit "Continue On Error" ist meist keine effektive Fehlerbehandlung möglich. Meist ist es sinnvoller, mit der Option RunOnErr zu arbeiten.

##### Beispiel

`ConOnErr=ON
ConOnErr=OFF`

#### DCF77DIS

##### Beschreibung

Mit diesem Bit läßt sich auf der Open-Maxi die DCF77-Auswertung an FREQ1 (bzw. FREQ) deaktivieren. Das sollte immer dann gemacht werden, wenn an FREQ1 etwas anderes als ein DCF77-Empfänger angeschlossen wird.

##### Beispiel

`Dcf77Dis=ON`

#### DCFCLKST

##### Beschreibung

Mit diesem Bit kann auf der Open-Maxi abgefragt werden, ob die interne Uhr ("RTC") wenigstens einmal auf die per DCF77-Signal empfangene Uhrzeit gesetzt wurde.

##### Beispiel

`IF DcfClkSt THEN PRINT "Uhr gestellt"`

#### DCFOK

##### Beschreibung

Mit diesem Bit kann auf der Open-Maxi abgefragt werden, ob das DCF77-Signal augenblicklich vom Controller als "okay" angesehen wird.

##### Beispiel

`IF DcfOk THEN PRINT "DCF77 okay"`

#### DCFSZ

##### Beschreibung

Mit diesem Bit kann auf der Open-Maxi abgefragt werden, ob laut DCF77-Signal die Sommerzeit aktiv ist. Es ist erst dann gültig, wenn DcfClkSt gesetzt ist.

##### Beispiel

`IF DcfSZ THEN PRINT "Sommerzeit"`

#### END2HOST

##### Beschreibung

Mit dieser Anweisung kann man nach einem Programmende (siehe END) gleich in den Host-Modus wechseln. Auf diese Weise kann man nach Programmende ein neues Programm laden, ohne die OM resetten zu müssen.

##### Beispiel

`End2Host=ON
END`

#### ESCIERR

##### Beschreibung

Mit diesem Bit kann auf der Open-Macro abgefragt werden, ob ein Empfangsfehler an der ESCI-Schnittstelle stattfand. Der kann durch einen Überlauf des Empfangsbuffers verursacht sein oder der Controller hat die NF-, FE- und/oder PE-Bits gesetzt. Beispiel siehe UseEsci.
EsciErr wird vom Betriebssystem gelöscht/resettet bei Benutzung von GET oder INPUT.

##### Beispiel

`IF EsciErr THEN PRINT "Fehler"`

#### EXTPERR

##### Beschreibung

Mit diesem Bit kann auf der Open-Maxi abgefragt werden, ob wenigstens ein für die Extended Ports zuständiger I²C-Portexpander PCF8574 kein ACKNOWLEDGE gesendet hat. In der Regel ist das der Fall, wenn der I²C-Portexpander nicht existiert oder die Verbindung zu ihm gestört ist. Das Bit wird von der Open-Maxi niemals zurückgesetzt, sondern muß vom Anwender nach der Auswertung auf 0 ("OFF") gesetzt werden.

##### Beispiel

`IF ExtPErr THEN PRINT "Fehler"`

#### FILEBYTE

##### Beschreibung

Mit dieser Anweisung kann die OM veranlaßt werden, Bytes statt Words in die Datendatei zu schreiben oder aus ihr zu lesen. Es wirkt sich auf PRINT#, INPUT# und FILEFREE aus.

##### Beispiel

`FileByte=ON`

#### FILECHG

##### Beschreibung

Dieses Flag signalisiert dem Betriebssystem, daß die Datei verändert wurde und CLOSE# deshalb das neue FILEEND in den Flash- oder EEPROM-Speicher schreiben muß.
Diese interne Variable sollte der Anwender nur auslesen und unverändert lassen.

##### Beispiel

`PRINT FileChg`

#### FILEERR

##### Beschreibung

Mit diesem Bit kann auf der Open-Maxi abgefragt werden, ob ein File-I/O-Error stattfand, also ob das I²C-EEPROM kein ACKNOWLEDGE sendet. In der Regel ist das der Fall, wenn das angesprochene EEPROM nicht existiert oder die Verbindung zu ihm gestört ist. Das Bit wird bei jedem OPEN#-Befehl gelöscht. Sobald das Bit gesetzt ist, werden alle nachfolgenden Dateibefehle ignoriert.
Diese interne Variable sollte der Anwender nur auslesen und unverändert lassen.

##### Beispiel

`IF FileErr THEN PRINT "Fehler"`

#### HWHSENAB

##### Beschreibung

Bei der Open-Maxi kann hiermit das Hardware-Handshake (RTS und CTS) an der ersten Seriellen Schnittstelle aktiviert werden.

##### Beispiel

`HwHsEnab=ON`

#### I2CDELAY

##### Beschreibung

Mit Hilfe dieser Byte-Variable läßt sich auf der Open-Maxi die Geschwindigkeit des I²C-Busses konfigurieren. Die Rechenvorschrift lautet circa 20E6/(8*i2cdelay+50).

##### Beispiel

`'POKE i2cdelay,255 'ca. 10 kHz I²C-Bustakt
POKE i2cdelay,20 'ca. 95 kHz (Defaultwert)
'POKE i2cdelay,8 'ca. 175 kHz
'POKE i2cdelay,1 'ca. 345 kHz`

##### Hinweis

Das I²C-LCD hat eine Geschwindigkeit von circa 1840 Zeichen pro Sekunde bei 95 kHz I²C-Bustakt. Versuche zeigten, daß das LCD selbst bei 345 kHz noch arbeitet. Dann werden circa 5200 Zeichen pro Sekunde ausgegeben. Aber dabei wird der PCF8574 außerhalb der Spezifikation betrieben.
Eine weitere Verringerung der Busfrequenz ist durch SLOWMODE ON möglich.

#### I2CEEPADR

##### Beschreibung

Mit Hilfe dieser Byte-Variable läßt sich auf der Open-Maxi die für die Datendatei verwendete I²C-Schreibadresse vom I²C-EEPROM setzen. Sie darf nur geändert werden, während die Datei geschlossen ist.

##### Beispiel

`POKE i2ceepadr,&b10100110 '(Defaultwert)`

#### I2CLCDADR

##### Beschreibung

Mit Hilfe dieser Byte-Variable läßt sich auf der Open-Maxi die für das I²C-LCD verwendete I²C-Schreibadresse vom I²C-Portexpander PCF8574 setzen. Es kann auch ein PCF8574A verwendet werden.

##### Beispiel

`POKE i2clcdadr,&h40 '(Defaultwert)`

#### IIARFND

##### Beschreibung

Dieses Flag signalisiert dem Betriebssystem, daß eine INLINE-Interrupt-Assemblerroutine gefunden wurde und diese anstatt einer Interruptroutine im SYCODE-Bereich verwendet werden soll.
Diese interne Variable sollte der Anwender nur auslesen und unverändert lassen.

##### Beispiel

`PRINT IiarFnd`

#### IRQACT

##### Beschreibung

Dieses Flag signalisiert dem Betriebssystem, daß eine BASIC-Interrupt-Routine augenblicklich ausgeführt wird.
Diese interne Variable sollte der Anwender nur auslesen und unverändert lassen.

##### Beispiel

`PRINT IrqAct`

#### IRQREQ

##### Beschreibung

Dieses Flag signalisiert dem Betriebssystem, daß ein IRQ-Interrupt detektiert wurde und deshalb die BASIC-Interruptroutine starten soll. Das Flag kann zum Beispiel verwendet werden, um die BASIC-Interruptroutine mittels Assemblerroutine im TIMOFL-Interrupt in periodischen Zeitabständen aufzurufen.

##### Beispiel

`PRINT IrqReq`

#### IRQSET

##### Beschreibung

Dieses Flag signalisiert dem Betriebssystem, daß eine BASIC-Interrupt-Routine per "INTERRUPT label" definiert wurde.
Diese interne Variable sollte der Anwender nur auslesen und unverändert lassen.

##### Beispiel

`PRINT IrqSet`

#### LCDEN2

##### Beschreibung

Konfiguriert die Open-Maxi so, daß nachfolgende LCD-Kommandos die zweite ENABLE-Leitung statt der ersten benutzen. Die zweite ENABLE-Leitung wird von LCDs mit zwei Controllern verwendet und belegt die gleiche Leitung wie die Hintergrundbeleuchtung.

##### Beispiel

`LcdEn2=ON`

#### LCDERR

##### Beschreibung

Dieses Bit wird auf der Open-Maxi gesetzt, wenn der für das I²C-LCD zuständige I²C-Portexpander PCF8574 kein ACKNOWLEDGE sendet. In der Regel wird dieses Bit gesetzt, wenn der angesprochene Portexpander nicht existiert oder die Verbindung zu ihm gestört ist.
Das Bit wird bei Verwendung von LCDINIT gelöscht/resettet.

##### Beispiel

`IF LcdErr THEN PRINT "Fehler"`

#### LCDLIGHT

##### Beschreibung

Bei der Open-Maxi kann hiermit die Hintergrundbeleuchtung des I²C-LCDs an- und ausgeschaltet werden. Diese Konfiguration wird erst nach dem nächsten LCD-Befehl sichtbar. Je nach Verschaltung kann dieses Bit invertiert sein. Die Hintergrundbeleuchtung belegt die gleiche Leitung wie die zweite ENABLE-Leitung (EN2).

##### Beispiel

`LcdLight=ON`

#### PRINTHEX

##### Beschreibung

Mit diesem Bit kann das Betriebssystem veranlaßt werden, alle mit PRINT über die Serielle Schnittstelle ausgegebenen Zahlen nicht im Dezimal- sondern im Hexadezimalformat auszugeben. Das ist besonders sinnvoll bei Adressen oder anderen Daten. Solange die hexadezimale Ausgabe aktiv ist, wird PrintSpc ignoriert.
Das Bit wirkt sich auch auf LCDPRINT aus.

##### Beispiel

`PrintHex=ON
PRINT &he8c2`

#### PRINTSPC

##### Beschreibung

Mit diesem Bit wird das Betriebssystem veranlaßt, vor die Ausgabe einer dezimalen Zahl mittels PRINT ein Leerzeichen (Space) zu setzen. Gerade während der Entwicklungsphase, in der zum Debugging oft Variableninhalte über PRINT-Befehle ausgegeben werden, führt das zu einer erheblichen Verringerung der Programmgröße. Solange die hexadezimale Ausgabe aktiv ist, wird PrintSpc ignoriert.
Das Bit wirkt sich auch auf LCDPRINT aus.

##### Beispiel

`PrintSpc=ON
PRINT 1;2;3`

#### PTAPE

##### Beschreibung

Existiert nur auf der Open-Maxi.
Mit diesem Register kann man die internen Pull-Up-Widerstände im Controller an den Digitalports PORT[1] bis PORT[8] abschalten. Nach jedem Reset aktiviert das Betriebssystem die Pull-Up-Widerstände an allen Ports. Die Widerstände haben eine Größe von typisch 45 kOhm (20 kOhm bis 65 kOhm) und legen die Ports auf High-Potential (5 Volt). Grundsätzlich wird der Pull-Up-Widerstand an einem Port vom Controller automatisch deaktiviert, solange der entsprechende Port kein auf Eingang geschalteter Digitalport ist.

##### Hinweis

Bei PTAPE handelt es sich um ein High-Page Register. Deshalb muß es per PEEK und POKE angesprochen werden.

##### Beispiel

`' PTAx: x -> 76543210
POKE PTAPE, &b11011111 'Pull-Up-Widerstand an PORT[6] (gleich PTA5)
'deaktivieren, alle anderen aktiviert lassen
PRINT PEEK(PTAPE)`

#### PTBPE

##### Beschreibung

Existiert nur auf der Open-Maxi.
Mit diesem Register kann man die internen Pull-Up-Widerstände im Controller an den Digitalports PORT[9] bis PORT[16] abschalten. Nach jedem Reset aktiviert das Betriebssystem die Pull-Up-Widerstände an allen Ports. Die Widerstände haben eine Größe von typisch 45 kOhm (20 kOhm bis 65 kOhm) und legen die Ports auf High-Potential (5 Volt). Grundsätzlich wird der Pull-Up-Widerstand an einem Port vom Controller automatisch deaktiviert, solange der entsprechende Port kein auf Eingang geschalteter Digitalport ist.

##### Hinweis

Bei PTBPE handelt es sich um ein High-Page Register. Deshalb muß es per PEEK und POKE angesprochen werden.

##### Beispiel

`' PTBx: x -> 76543210
POKE PTBPE, &b11111111 'alle Pull-Up-Widerstände aktivieren
PRINT PEEK(PTBPE)`

#### PTEPE

##### Beschreibung

Existiert nur auf der Open-Maxi.
Mit diesem Register kann man die internen Pull-Up-Widerstände im Controller an den Digitalports PORT[33] bis PORT[40] abschalten. Nach jedem Reset aktiviert das Betriebssystem die Pull-Up-Widerstände an allen Ports. Die Widerstände haben eine Größe von typisch 45 kOhm (20 kOhm bis 65 kOhm) und legen die Ports auf High-Potential (5 Volt). Grundsätzlich wird der Pull-Up-Widerstand an einem Port vom Controller automatisch deaktiviert, solange der entsprechende Port kein auf Eingang geschalteter Digitalport ist.

##### Hinweis

Bei PTEPE handelt es sich um ein High-Page Register. Deshalb muß es per PEEK und POKE angesprochen werden.

##### Beispiel

`' PTEx: x -> 76543210
POKE PTEPE, &b11111111 'alle Pull-Up-Widerstände aktivieren
PRINT PEEK(PTEPE)`

#### PULLUPA

##### Beschreibung

Existiert nur auf der Open-Macro.
Mit diesem Register kann man die internen Pull-Up-Widerstände im Controller an den Digitalports PORT[1] bis PORT[6] abschalten. Nach jedem Reset aktiviert das Betriebssystem die Pull-Up-Widerstände an allen Ports. Die Widerstände haben eine Größe von 26 kOhm (+/- 10 kOhm) und legen die Ports auf High-Potential (5 Volt). Grundsätzlich wird der Pull-Up-Widerstand an einem Port vom Controller automatisch deaktiviert, solange der entsprechende Port kein auf Eingang geschalteter Digitalport ist.
Wenn die Analog-Digital-Ports AD[1] bis AD[6] verwendet werden, führen die internen Pull-Up-Widerstände an den Digitalports oft zur Verfälschung des Meßwerts, da sie vom Controller vor jeder Messung deaktiviert und nach der Messung wieder aktiviert werden. Deshalb sollten die Widerstände an den entsprechenden Ports mit Hilfe von PULLUPA abgeschaltet werden.
Zusätzlich steuert das oberste Bit in diesem Register, ob an PORT[5] der Takt des internen Oszillators (BUSCLKX4) ausgegeben werden soll.

##### Verfügbarkeit

`Open-Macro: ja
Open-Maxi: nein (es gibt unter anderem PTAPE, PTBPE und PTEPE)`

##### Beispiel

`' PTAx: x -> 543210
PULLUPA = &b00011111 'Pull-Up-Widerstand an PORT[6] (gleich PTA5)
'deaktivieren, alle anderen aktiviert lassen`

#### PULLUPB

##### Beschreibung

Existiert nur auf der Open-Macro.
Mit diesem Befehl kann man die internen Pull-Up-Widerstände im Controller an den Digitalports PORT[9] bis PORT[16] abschalten. Nach jedem Reset aktiviert das Betriebssystem die Pull-Up-Widerstände an allen Ports. Die Widerstände haben eine Größe von 26 kOhm (+/- 10 kOhm) und legen die Ports auf High-Potential (5 Volt). Grundsätzlich wird der Pull-Up-Widerstand an einem Port vom Controller automatisch deaktiviert, solange der entsprechende Port kein auf Eingang geschalteter Digitalport ist.
Auf der Open-Macro können die Pull-Up-Widerstände an PORT[9] bis PORT[14] das Meßergebnis der AD-Ports AD[9] bis AD[14] verfälschen. Es gilt das bei PULLUPA Geschriebene.

##### Verfügbarkeit

`Open-Macro: ja
Open-Maxi: nein (es gibt unter anderem PTAPE, PTBPE und PTEPE)`

##### Beispiel

`' PTBx: 76543210
PULLUPB = &b11111111 'alle Pull-Up-Widerstände ein`

#### REALPOP

##### Beschreibung

Mit diesem Bit kann man die OM veranlassen, beim Rechenstack ein echtes LIFO-Stackhandling zu benutzen. Das heißt, ein POP entfernt den "Top-Of-Stack" (TOS) und ein REMOVETOS ist unnötig.
RealPop bewirkt ein langsameres Stackhandling und hat, wenn keine BASIC-Interruptroutine verwendet werden soll, kaum einen Vorteil. Wenn aber RealPop und eine BASIC-Interruptroutine verwendet werden, teilen sich das Hauptprogramm und die Interruptroutine den Rechenstack, so daß der Rechenstack bei Start der Interruptroutine nicht mehr zwischengespeichert werden muß und so 17 Byte zusätzlicher Variablenspeicher auch bei Benutzung einer BASIC-Interruptroutine zur Verfügung steht. Da dann aber insgesamt nur 8 Stackeinträge zur Verfügung stehen, besteht die Gefahr von Stackfehlern, die zu heimtückischen Rechenfehlern im Hauptprogramm führen können.
Auf der Open-Maxi sollte das echte Stackhandling nicht verwendet werden, denn es beißt sich mit BEEP, POKE und POKEW.

##### Beispiel

`RealPop=ON 'echtes Stackhandling aktivieren`

#### RUNONERR

##### Beschreibung

Normalerweise unterbricht die OM die Programmausführung, sobald ein Fehler auftritt. Durch Setzen dieses Bits kann man die OM jedoch anweisen, das BASIC-Programm bei einem Fehler neu zu starten. Die Daten der verwendeten Variablen bleiben dabei erhalten. Das Betriebssystem wird reinitalisiert. Der Fehlergrund steht in der internen Variable ERR und die Adresse des Bytes hinter dem fehlerhaften Tokenbefehl steht in ERRADR. Siehe dazu die Anmerkungen bei ERR.
Siehe dazu auch ERR, ERRADR, PRINT# und Beispiel im Forum.

##### Hinweis

Diese Funktion ist dazu vorgesehen, um an den Beginn des Programms eine Fehlerbehandlungsroutine zu stellen und die Programmausführung bei Eintritt eines Fehlers zu beenden. Das Auftreten eines Fehlers ist ein Hinweis, daß irgendetwas im Programm nicht korrekt abläuft. Das Programm sollte deshalb nicht einfach nochmals durchlaufen werden. Zumal der RAM-Speicher und somit auch das User-RAM mit den Variablen nicht reinitalisiert wurden.

##### Beispiel

`RunOnErr=ON
IF ERR THEN
PRINT "Es trat der Fehler Nummer ";ERR;" auf!"
END
END IF
' restliches Programm`

#### SCIERR

##### Beschreibung

Mit diesem Bit kann auf der Open-Maxi abgefragt werden, ob ein Empfangsfehler an der ersten Seriellen Schnittstelle stattfand. Der kann durch einen Überlauf des Empfangsbuffers verursacht sein oder der Controller hat die NF-, FE- und/oder PE-Bits gesetzt.
SciErr wird vom Betriebssystem gelöscht/resettet bei Benutzung von GET oder INPUT.

##### Beispiel

`IF SciErr THEN PRINT "Fehler"`

#### UFILEEND

##### Beschreibung

Diese Word-Variable enthält auf der Open-Maxi den Fileende-Zeiger der Datendatei. Er enthält erst nach dem Öffnen der Datei (siehe OPEN# FOR) einen gültigen Wert.

##### Beispiel

`PRINT PEEKW(ufileend)`

#### UIRADC

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den ADC-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iADC und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich auf der Open-Maxi selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRAdc=ON`

#### UIRESCIE

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Macro eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "ESCI error"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iESCIe und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIREsciE=ON`

#### UIRESCIR

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Macro eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "ESCI receive"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iESCIr und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIREsciR=ON`

#### UIRESCIT

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Macro eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "ESCI transmit"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iESCIt und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIREsciT=ON`

#### UIRICG

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Internal Clock Generator (ICG)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iICG und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.

##### Beispiel

`UIRIcg=ON`

#### UIRIIC1

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Inter-Integrated Circuit (I2C, IIC)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iIIC1 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRIic1=ON`

#### UIRIRQ

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den IRQ-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iIRQ und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.

##### Beispiel

`UIRIrq=ON`

#### UIRKYB

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den KEYB-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iKYB und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.

##### Beispiel

`UIRKyb=ON`

#### UIRLVD

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Low Voltage Detect (LVD)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iLVD und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRLvd=ON`

#### UIRRTI

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Real-Time Interrupt (RTI)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iRTI und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRRti=ON`

#### UIRSCI1E

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Communications Interface 1 - Error"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSCI1e und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSci1e=ON`

##### Hinweis

Das Open-Maxi-Betriebssystem verwendet das SCI2. Das SCI1 ist frei.

#### UIRSCI1R

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Communications Interface 1 - Receive"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSCI1r und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSci1r=ON`

##### Hinweis

Das Open-Maxi-Betriebssystem verwendet das SCI2. Das SCI1 ist frei.

#### UIRSCI1T

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Communications Interface 1 - Transmit"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSCI1t und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSci1t=ON`

##### Hinweis

Das Open-Maxi-Betriebssystem verwendet das SCI2. Das SCI1 ist frei.

#### UIRSCI2E

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Communications Interface 2 - Error"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSCI2e und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSci2e=ON`

##### Hinweis

Das Open-Maxi-Betriebssystem verwendet das SCI2. Das SCI1 ist frei.

#### UIRSCI2R

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Communications Interface 2 - Receive"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSCI2r und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern, wenn die Anwenderroutine mit gesetztem Carry-Bit beendet wird.

##### Beispiel

`UIRSci2r=ON`

##### Hinweis

Das Open-Maxi-Betriebssystem verwendet das SCI2. Das SCI1 ist frei.

#### UIRSCI2T

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Communications Interface 2 - Transmit"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSCI2t und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSci2t=ON`

##### Hinweis

Das Open-Maxi-Betriebssystem verwendet das SCI2. Das SCI1 ist frei.

#### UIRSPI

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Serial Peripheral Interface (SPI)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSPI und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSpi=ON`

#### UIRSPIR

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Macro eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "SPI receive"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSPIr und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSpiR=ON`

#### UIRSPIT

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Macro eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "SPI transmit"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSPIt und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Anwender muß sich selbst um das Rücksetzen der Interruptanforderung kümmern.

##### Beispiel

`UIRSpiT=ON`

#### UIRSWI

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den SWI-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iSWI und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Auf der OM werden Firmwareroutinen per "LDX #funktionsnummer : SWI" aufgerufen, damit Assemblermodule, die für die OM geschrieben werden, auch bei verändertem Speicherlayout lauffähig bleiben. Wenn der Anwender eine Routine in diesen SWI-Interrupt einbindet, dann muß das X-Register vor Beendigung der Routine wieder mit der Funktionsnummer geladen werden, falls die Betriebssystemfunktion nach Ausführung der Userroutine aktiviert bleiben soll ("CLC"). Es ist natürlich auch denkbar, auf diese Weise eigene Firmwareroutinen in das System einzubinden.

##### Beispiel

`UIRSwi=ON`

#### UIRTIM0

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den TIM0-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTIM0 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der TIM0-Interrupt wird auf der OM normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bCH0IE,TSC0" (Open-Macro), bzw. "BSET bCH0IE,TPM1C0SC" (Open-Maxi) aktiviert werden.

##### Beispiel

`UIRTim0=ON`

#### UIRTIM1

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den TIM1-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTIM1 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der TIM1-Interrupt wird auf der OM normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bCH1IE,TSC1" (Open-Macro), bzw. "BSET bCH1IE,TPM1C1SC" (Open-Maxi) aktiviert werden.

##### Beispiel

`UIRTim1=ON`

#### UIRTIM2

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "TIM1 Channel 2"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTIM2 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der TIM2-Interrupt wird auf der Open-Macro normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bCH2IE,TSC2" aktiviert werden.
Auf der Open-Maxi wird hiermit der "BEEP-Interrupt" realisiert.

##### Beispiel

`UIRTim2=ON`

#### UIRTIM3

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "TIM1 Channel 3"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTIM3 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der TIM3-Interrupt wird auf der Open-Macro normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bCH3IE,TSC3" aktiviert werden.
Auf der Open-Maxi wird hiermit der "20-ms-Interrupt" realisiert.

##### Beispiel

`UIRTim3=ON`

#### UIRTIM4

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Timer/PWM-Module 1 - Channel 4 (TPM1CH4)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTIM4 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Auf der Open-Maxi wird hiermit der "FREQ1-Interrupt" realisiert.

##### Beispiel

`UIRTim4=ON`

#### UIRTIM5

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Timer/PWM-Module 1 - Channel 5 (TPM1CH5)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTIM5 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Auf der Open-Maxi wird hiermit der "FREQ2-Interrupt" realisiert.

##### Beispiel

`UIRTim5=ON`

#### UIRTOFL

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den TIMOFL-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTOFL und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der TIMOFL-Interrupt wird auf der Open-Macro als TIMER-Interrupt verwendet und periodisch alle 20 ms aufgerufen ("20-ms-Interrupt").
Auf der Open-Maxi wird dieser Interrupt normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bTOIE,TPM1SC" aktiviert werden. Der "20-ms-Interrupt" wird auf der Open-Maxi per "Timer/PWM-Module 1 - Channel 3 (TPM1CH3)" realisiert. Siehe UIRTim3.

##### Beispiel

`UIRTofl=ON`

#### UIRTPM2C0

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Timer/PWM-Module 2 - Channel 0 (TPM2CH0)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTPM2C0 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Channel 0 vom TPM2 wird auf der Open-Maxi für PWM-Ausgabe an DA[1] verwendet.
Dieser Interrupt wird auf der OM normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bCH0IE,TPM2C0SC" aktiviert werden.

##### Beispiel

`UIRTpm2C0=ON`

#### UIRTPM2C1

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Timer/PWM-Module 2 - Channel 1 (TPM2CH1)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTPM2C1 und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Der Channel 1 vom TPM2 wird auf der Open-Maxi für PWM-Ausgabe an DA[2] verwendet.
Dieser Interrupt wird auf der OM normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bCH1IE,TPM2C1SC" aktiviert werden.

##### Beispiel

`UIRTpm2C1=ON`

#### UIRTPM2OFL

##### Beschreibung

Durch Setzen dieses Bits läßt sich auf der Open-Maxi eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den "Timer/PWM-Module 2 - Overflow (TPM2OVF)"-Interrupt einbinden. Sobald der Interrupt auftritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTPM2OFL und im X-Register die Adresse von FREERAM übergeben wird. Die Routine sollte mit "RTS" und gelöschtem Carry-Bit ("CLC") beendet werden.
Dieser Interrupt wird auf der OM normalerweise nicht verwendet und muß daher vom Anwender zunächst per "BSET bTOIE,TPM2SC" aktiviert werden.

##### Beispiel

`UIRTpm2Ofl=ON`

#### URILLTOK

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich starten, sobald der Interpreter auf einen illegalen Tokenbefehl stößt. Sobald dieser Fall eintritt, wird die Assemblerroutine aufgerufen, wobei im Akkumulator der Wert #iTOK und im X-Register die Adresse von FREERAM übergeben wird. Auf FREERAM steht das illegale Token. Die Routine sollte mit "RTS" beendet werden. Falls mit gelöschtem Carry-Bit ("CLC") beendet wird, führt der Interpreter das im Akkumulator stehende Token aus. Wird dagegen mit gesetztem Carry-Bit ("STC") beendet, fährt das System mit dem nächsten Tokenbefehl fort.

##### Beispiel

`URIllTok=ON`

#### URTOK

##### Beschreibung

Durch Setzen dieses Bits läßt sich eine Inline-Interrupt-Assemblerroutine (IIAR) oder eine Assemblerroutine im SYSCODE-Bereich in den Interpreter einbinden. Die Routine wird jedesmal gestartet, nachdem ein neuer Tokenbefehl aus dem Speicher geholt wurde. Das ist unmittelbar bevor der Tokenbefehl vom Interpreter ausgeführt wird. Mit Hilfe der Routine läßt sich zum Beispiel ein In-System-Debugger realisieren. Oder man könnte die Programmausführung unterbrechen, sobald eine Variable einen illegalen Wert annimmt.
Der Assemblerroutine wird im Akkumulator der Wert #iTOK und im X-Register die Adresse von FREERAM übergeben. Auf FREERAM steht das aus dem Speicher geholte Token. Die Routine sollte mit "RTS" beendet werden. Falls mit gelöschtem Carry-Bit ("CLC") beendet wird, führt der Interpreter das im Akkumulator stehende Token aus. Wird dagegen mit gesetztem Carry-Bit ("STC") beendet, fährt das System mit dem nächsten Tokenbefehl fort.

##### Beispiel

`URTok=ON`

#### USEESCI

Die Open-Macro bietet eine hardwaremäßig implementierte 2. Serielle Schnittstelle (ESCI). Die TXD-Leitung der ESCI liegt am PORT[14] und RXD am PORT[13]. Auf dem Starterboard von CCTools oder dem zweiten PE-Board auf der offiziellen OM-Website kann der Jumper für RS232 auf Dual-Wire umgeschaltet und PORT[14] mit PORT[1] und PORT[13] mit PORT[2] verbunden werden, um die ESCI zu testen oder zu nutzen.

##### Beispiel

`INCLUDE "omac.def"
UseEsci=ON 'ESCI benutzen (beim nächsten BAUD, PUT, GET,
' PRINT, INPUT oder RXD wird umgeschaltet)
BAUD R9600 'R19200 'R38400
WHILE TRUE
PRINT "Hallo Welt! ";EsciErr
WHILE RXD
PRINT "empfangen: ";GET
WEND
PAUSE 100
WEND`

##### Hinweis

Die interne Variable EsciErr ist in OMAC.DEF definiert. Sie bedeutet "mindestens ein Empfangsfehler an der ESCI". Gelöscht/resettet wird EsciErr vom Betriebssystem bei Benutzung von GET oder INPUT. Das obige Beispiel kann man folgendermaßen testen: Im Terminalprogramm während der Programmabarbeitung (während PAUSE) mehr als 8 Tasten drücken. Dann gibt es einen Überlauf im Empfangsbuffer, weil dieser nur 8 Byte groß ist.

#### VERSION

##### Beschreibung

Mit dieser Variable kann die Versionsnummer vom geladenen Betriebsystem abgefragt werden. Nach Anlegen der Versorgungsspannung wird in BYTE[24] diese Nummer hinterlegt. Eine Variable auf BYTE[24] kann ohne Einschränkungen verwendet werden, wenn die Versionsnummer nicht benötigt wird.

##### Hinweis

Nach Programmstart ohne Fehler wird vom Betriebssystem der gesamte Variablenspeicher mit Ausnahme von VERSION auf 0 gesetzt. Damit alle Variablen auf 0 stehen, sollte der Anwender bei Programmstart VERSION=0 ausführen.

##### Beispiel

`PRINT VERSION
VERSION=0 'Versionsnummer auf 0 setzen`

### Schlüsselwortliste

Hier die thematisch sortierte Liste aller vom OCBASIC-Compiler derzeit unterstützten Schlüsselwörter und durch die Definitionsdateien erstellten neuen internen Variablen. Durch Anklicken des jeweiligen Schlüsselworts kann zur Stelle in dieser Dokumentation gesprungen werden, an der die ausführliche Beschreibung zu finden ist. Einige Schlüsselwörter passen in verschiedene Themenbereiche. Sie wurden dennoch nur einmal aufgeführt.

Anweisungen an den Compiler
Schlüsselwort | Kurzbeschreibung | Beispiel
INCLUDE | Datei an die aktuelle Position des Sourcecodes einfügen | INCLUDE "omac.def"
INLINE | Daten an die aktuelle Position der Ausgabedatei einfügen | INLINE "Pizza-Uhr von D.H.",0
OPTION | Compiler auf Controllertype konfigurieren | OPTION openmaxi
Definitionen
Schlüsselwort | Kurzbeschreibung | Beispiel
AD | Analogen Eingang definieren | DEFINE adpoti AD[6]
BIT | Bitvariable definieren | DEFINE bit7vonzahl BIT[8] OF zahl
BYTE | Bytevariable definieren | DEFINE variable BYTE
BYTEPORT | Byteport definieren | DEFINE port_a BYTEPORT[1]
DA | Digital-Analog-Port (PWM) definieren | DEFINE pwm_port DA[1]
DEFINE | Bezeichner (Port, Variable oder Konstante) definieren | DEFINE a,b,c BYTE
DIM | Bezeichner (Port, Variable oder Konstante) definieren | DIM a,b,c BYTE
IVAR | Neue interne Variable definieren | DEFINE PULLUPA IVAR[140]
PORT | Digitalport (Bitport) definieren | DEFINE led PORT[4]
WORD | Wordvariable definieren | DEFINE variable1 WORD
WORDPORT | Wordport definieren | DEFINE alle_ports WORDPORT[1]
ZEIGER (^, @) | USER-RAM-Zeiger definieren und verwenden | @pb=234
Port-Ein-/Ausgabe
Schlüsselwort | Kurzbeschreibung | Beispiel
BEEP | Rechtecksignal (Ton) an einem Digitalport ausgeben | BEEP 250, 50, ton_port
DEACT | Ausgabeport auf Eingang schalten | port1=OFF : DEACT port1
FREQ | Frequenz am FREQ-Pin (bzw. PORT[3]) abfragen | FREQ=50 : PRINT FREQ
FREQ2 | Frequenz am FREQ2-Pin abfragen | PRINT FREQ2
PTAPE | Interne Pull-Up-Widerstände an BYTEPORT[1] | POKE PTAPE,&b11111111
PTBPE | Interne Pull-Up-Widerstände an BYTEPORT[2] | POKE PTBPE,&b11111111
PTEPE | Interne Pull-Up-Widerstände an BYTEPORT[5] | POKE PTEPE,&b11111111
PULLUPA | Interne Pull-Up-Widerstände an BYTEPORT[1] | PULLUPA=&b00111111
PULLUPB | Interne Pull-Up-Widerstände an BYTEPORT[2] | PULLUPB=&b11111111
PULSE | Puls an einem Ausgabedigitalport ausgeben | led=OFF : PULSE led
TOG | Ausgabedigitalport umschalten | led=ON : TOG led
EXTPERR | Extended Ports: ein I²C-Portexpander sendet kein ACK | IF ExtPErr THEN PRINT "Fehler"
Mathematische Berechnungen
Schlüsselwort | Kurzbeschreibung | Beispiel
&B | Konstante im binären Zahlensystem | &B10011001
&H | Konstante im hexadezimalen Zahlensystem | &H1FFE
ABS | Berechnung des Absolutbetrags | y = ABS(-1)
ADD | Schnelle und platzsparende Addition bei User-Variablen | ADD a,1
AND | Logische und bitweise UND-Verknüpfung | IF x>10 AND x<20 THEN y=x
ASC | Stringkonstante in ASCII-Zeichen wandeln | PUT ASC("?")
CARRY | Carry nach Berechnungen | PRINT Carry
MAX | Größeren Wert ermitteln | z=MAX(x,10)
MIN | Kleineren Wert ermitteln | z=MIN(x,10)
MOD | Rest einer ganzzahligen Division | PRINT 10 MOD 6
NAND | UND-Verknüpfung mit anschließender Negation (NOT) | x=a NAND b
NOR | ODER-Verknüpfung mit anschließender Negation (NOT) | x=a NOR b
NOT | Logische und bitweise Negation (1er Komplement) | x=NOT(y)
OFF | Vordefinierte Konstante für 0 (logisch unwahr, Port low) | Led=OFF
ON | Vordefinierte Konstante für -1 (logisch wahr, Port high) | Led=ON
OR | Logische und bitweise ODER-Verknüpfung | y=a OR b
POP | Top-Of-Stack (TOS) des Rechenstacks auslesen | a=POP
PUSH | Wert auf dem Rechenstack ablegen | PUSH 123
RAND | Zufallszahl im Integerformat generieren | x=RAND
RANDOMIZE | Zufallszahlengenerator initialisieren | RANDOMIZE TIMER
REMOVETOS | Top-Of-Stack (TOS) des Rechenstacks entfernen | REMOVETOS
SGN | Mathematische Signum-Funktion | z=SGN(x)
SHL | Bitweises arithmetisches Linksschieben | x=x SHL 3
SHR | Bitweises arithmetisches Rechtsschieben | x=x SHR 3
SQR | Ganzzahliger Näherungswert für die Quadratwurzel | z=SQR(x)
SUB | Schnelle und platzsparende Subtraktion bei User-Variablen | SUB a,1
XOR | Logische und bitweise Exclusiv-ODER-Verknüpfung | x=a XOR b
Programmablaufsteuerung
Schlüsselwort | Kurzbeschreibung | Beispiel
DBNZ | Schnelle DBNZ-Schleife ausführen | DBNZ loop
DBNZCTR | Zähler für DBNZ-Schleifen | DBNZCTR=15
ELSE | Alternativzweig bei IF..THEN | IF x=0 THEN x=1 ELSE x=2
END | Programmausführung beenden | END
END2HOST | Nach Programmende in den Host-Modus wechseln | End2Host=ON : END
FOR TO NEXT | Programmschleife | FOR i=32 TO 255 : PUT i : NEXT i
FUNCTION | Funktion definieren | FUNCTION funktion(a,b)
GOSUB | Subroutine aufrufen | GOSUB unterprogramm1
GOTO | Unbedingter Sprung zu einem Label (Sprungziel) | GOTO endlos
IF THEN | Bedingte Befehlsausführung | IF x>10 THEN END
ON GOSUB | Unterroutinenaufruf in Abhängigkeit eines Wertes | ON x GOSUB label1, label2
ON GOTO | Programmsprung in Abhängigkeit eines Wertes | ON x GOTO label1, label2
PAUSE | Programmunterbrechung für Vielfache von 20 Millisekunden | PAUSE 50
PROCEDURE | Unterprogramm (Subroutine, Prozedur) definieren | PROCEDURE subroutine(a,b)
REPEAT UNTIL | Fußgesteuerte Schleife mit Abbruchbedingung | a=0 : REPEAT : a=a+1 : UNTIL a>9
RETURN | Aus einer Subroutine oder einer Funktion zurückkehren | RETURN
Sprungziele (#) | Ziele der Sprungoperationen GOSUB und GOTO | #label
STEP | Schrittweite bei einer FOR-Programmschleife | FOR i=1 TO 9 STEP 2 : NEXT i
WAIT | Auf Eintreten einer Bedingung warten | WAIT taste=ON
WHILE WEND | Kopfgesteuerte Schleife mit Einstiegsbedingung | WHILE taste : WEND
BASIC-Interruptroutine
Schlüsselwort | Kurzbeschreibung | Beispiel
INTERRUPT | BASIC-Interruptroutine vereinbaren | INTERRUPT basicirq
RETURN INTERRUPT | Aus der BASIC-Interruptroutine zurückkehren | RETURN INTERRUPT
Serielle Schnittstelle
Schlüsselwort | Kurzbeschreibung | Beispiel
BAUD | Baudrate der Seriellen Schnittstelle einstellen | BAUD R9600
CTS | Test, ob die CTS-Leitung aktiv ist | IF CTS THEN GET x
ESCIERR | Abfrage, ob Empfangsfehler an der ESCI | IF EsciErr THEN PRINT "Fehler"
GET | Byte (Zeichen) von der Seriellen Schnittstelle lesen | GET x
HANDSHAKE | Hardware-Handshake auf der RTS- und CTS-Leitung (obsolet) | HANDSHAKE ON
HWHSENAB | Hardware-Handshake auf der RTS- und CTS-Leitung | HwHsEnab=ON
INPUT | Zahlenwert im Textformat von der Seriellen Schnittstelle einlesen | INPUT x
PRINT | Werte und Texte über die Serielle Schnittstelle ausgeben | PRINT "Wert ist ";wert
PRINTHEX | Bei PRINT alle Zahlen im Hexadezimalformat ausgeben | PrintHex=ON
PRINTSPC | Bei PRINT dezimale Zahlen mit führendem Leerzeichen ausgeben | PrintSpc=ON
PUT | Byte über die Serielle Schnittstelle ausgeben | PUT x
RXD | Test, ob ein Byte seriell empfangen wurde | IF RXD THEN GET x
SCIERR | Abfrage, ob Empfangsfehler an der Seriellen Schnittstelle | IF SciErr THEN PRINT "Fehler"
USEESCI | ESCI- statt Semi-Dual-Wire-RS232 benutzen | UseEsci=ON : BAUD R9600
Datenspeicherung
Schlüsselwort | Kurzbeschreibung | Beispiel
APPEND | Datei zum Anfügen von Daten öffnen | OPEN# FOR APPEND
CLOSE# | Datei schließen | CLOSE#
EOF | Test auf Dateiende beim Auslesen der Datei | IF NOT EOF THEN INPUT# a
FILEBYTE | PRINT#, INPUT# und FILEFREE im Byte- statt Wordformat | FileByte=ON
FILEERR | File-I/O-Error - das I²C-EEPROM sendet kein ACK | IF FileErr THEN PRINT "Fehler"
FILEFREE | Test auf freien Speicherplatz vor dem Schreiben in die Datei | IF FILEFREE>0 THEN PRINT# a
FILEPOS | Dateipositions-Zeiger | PRINT FILEPOS
I2CEEPADR | I²C-Schreibadresse vom I²C-EEPROM setzen | POKE i2ceepadr,&b10100110
INPUT# | Zahlenwert aus der Datei einlesen | INPUT# x
LOOKTAB | Word aus einer Datentabelle lesen | PRINT LOOKTAB(tabelle1, mess)
LOOKTABBYTE | Byte aus einer Datentabelle lesen | PRINT LOOKTABBYTE(tabelle2, mess)
OPEN# | Datei im Modus Schreiben, Anfügen oder Lesen öffnen | OPEN# FOR READ
PRINT# | Wert in die Datei schreiben | IF FILEFREE>0 THEN PRINT# 123
READ | Datei zum Auslesen von Daten öffnen | OPEN# FOR READ
TABLE | Datentabelle definieren | TABLE tab2 BYTE "datei.tab"
TABEND | Abschluß einer bei TABLE eingegebenen Werteliste | TABLE tab1 : 17 25 4 5 : TABEND
UFILEEND | Fileende-Zeiger der Datei | PRINT PEEKW(ufileend)
WRITE | Datei zum Schreiben neuer Daten öffnen | OPEN# FOR WRITE
Echtzeituhr
Schlüsselwort | Kurzbeschreibung | Beispiel
CLOCKDIS | Weiterzählen der Uhr deaktivieren | ClockDis=ON
DAY | Tagwert der Echtzeituhr | PRINT DAY
DOW | Wochentagwert der Echtzeituhr | IF DOW = 1 THEN PRINT "Montag"
HOUR | Stundenwert der Echtzeituhr | PRINT HOUR
MINUTE | Minutenwert der Echtzeituhr | PRINT MINUTE
MONTH | Monatswert der Echtzeituhr | PRINT MONTH
SECOND | Sekundenwert der Echtzeituhr | PRINT SECOND
TIMER | 20-ms-Timer | x=TIMER
YEAR | Jahrwert der Echtzeituhr | PRINT YEAR
DCFCLKST | DCF77: "Interne Uhr der OM wurde gestellt" | IF DcfClkSt THEN PRINT "Uhr gestellt"
DCFOK | DCF77: "DCF-Signal zur Zeit okay" | IF DcfOk THEN PRINT "DCF77 okay"
DCFSZ | DCF77: "Sommerzeit ist aktiv" | IF DcfSZ THEN PRINT "Sommerzeit"
I²C-LCD
Schlüsselwort | Kurzbeschreibung | Beispiel
I2CLCDADR | I²C-Schreibadresse vom I²C-Portexpander setzen | POKE i2clcdadr,&h40
LCDCLS | Bildschirm vom LCD löschen | LCDCLS
LCDCMD | Kommando zum LCD schicken | LCDCMD &b00001111
LCDINIT | LCD initialisieren | LCDINIT
LCDEN2 | Zweite ENABLE-Leitung verwenden | LcdEn2=ON
LCDERR | Der I²C-Portexpander sendet kein ACK | IF LcdErr THEN PRINT "Fehler"
LCDLIGHT | Hintergrundbeleuchtung ein- oder ausschalten | LcdLight=ON
LCDLOCATE | Cursor im LCD positionieren | LCDLOCATE y,x
LCDPRINT | String oder Zahl auf dem LCD darstellen | LCDPRINT "Zahl:";-12345
LCDPUT | Zeichen auf dem LCD darstellen | LCDPUT ASC("!")
Fehlerverfolgung
Schlüsselwort | Kurzbeschreibung | Beispiel
CONONERR | Programmausführung trotz Fehler fortsetzen (obsolet) | ConOnErr=ON
ERR | Fehlergrund ermitteln | IF ERR THEN PRINT ERR : END
ERRADR | Fehlerstelle im Tokencode | PRINT ERRADR
RUNONERR | Programm bei einem Fehler neustarten | RunOnErr=ON
Speicherzellen lesen oder beschreiben
Schlüsselwort | Kurzbeschreibung | Beispiel
PEEK | Ein Byte aus dem Speicher lesen | PRINT PEEK(i2cdelay)
PEEKW | Ein Word aus dem Speicher lesen | PRINT PEEKW(ufileend)
POKE | Ein Byte in den Speicher schreiben | POKE i2clcdadr,&h40
POKEW | Ein Word in den Speicher schreiben | POKEW freq1tmp,1
Assemblerprogrammierung
Schlüsselwort | Kurzbeschreibung | Beispiel
ASSEMBLER (!) | Assemblerbefehl in das Programm einfügen | ! lda variable
FREERAM | Für Assemblerroutinen reservierter RAM-Speicher | FREERAM=123
SYS | Aufruf einer Maschinensprache-Routine | SYS &HFD00
SYSCODE | S19-Datei mit Assembler-Routinen in das Programm einbinden | SYSCODE "test.s19"
SYSEND | Abschluß einer mit SYSCODE direkt eingegebenen Byteliste | SYSCODE &H81 SYSEND
UIRADC | Assemblerroutine in den ADC-Interrupt einbinden | UIRAdc=ON
UIRESCIE | Assemblerroutine in den ESCI-ERROR-Interrupt einbinden | UIREsciE=ON
UIRESCIR | Assemblerroutine in den ESCI-RECEIVE-Interrupt einbinden | UIREsciR=ON
UIRESCIT | Assemblerroutine in den ESCI-TRANSMIT-Interrupt einbinden | UIREsciT=ON
UIRICG | Assemblerroutine in den ICG-Interrupt einbinden | UIRIcg=ON
UIRIIC1 | Assemblerroutine in den IIC1-Interrupt einbinden | UIRIic1=ON
UIRIRQ | Assemblerroutine in den IRQ-Interrupt einbinden | UIRIrq=ON
UIRKYB | Assemblerroutine in den KEYB-Interrupt einbinden | UIRKyb=ON
UIRLVD | Assemblerroutine in den LVD-Interrupt einbinden | UIRLvd=ON
UIRRTI | Assemblerroutine in den RTI-Interrupt einbinden | UIRRti=ON
UIRSCI1E | Assemblerroutine in den SCI1-ERROR-Interrupt einbinden | UIRSci1e=ON
UIRSCI1R | Assemblerroutine in den SCI1-RECEIVE-Interrupt einbinden | UIRSci1r=ON
UIRSCI1T | Assemblerroutine in den SCI1-TRANSMIT-Interrupt einbinden | UIRSci1t=ON
UIRSCI2E | Assemblerroutine in den SCI2-ERROR-Interrupt einbinden | UIRSci2e=ON
UIRSCI2R | Assemblerroutine in den SCI2-RECEIVE-Interrupt einbinden | UIRSci2r=ON
UIRSCI2T | Assemblerroutine in den SCI2-TRANSMIT-Interrupt einbinden | UIRSci2t=ON
UIRSPI | Assemblerroutine in den SPI-Interrupt einbinden | UIRSpi=ON
UIRSPIR | Assemblerroutine in den SPI-RECEIVE-Interrupt einbinden | UIRSpiR=ON
UIRSPIT | Assemblerroutine in den SPI-TRANSMIT-Interrupt einbinden | UIRSpiT=ON
UIRSWI | Assemblerroutine in den SWI-Interrupt einbinden | UIRSwi=ON
UIRTIM0 | Assemblerroutine in den TIM0-Interrupt einbinden | UIRTim0=ON
UIRTIM1 | Assemblerroutine in den TIM1-Interrupt einbinden | UIRTim1=ON
UIRTIM2 | Assemblerroutine in den TIM2-Interrupt einbinden | UIRTim2=ON
UIRTIM3 | Assemblerroutine in den TIM3-Interrupt einbinden | UIRTim3=ON
UIRTIM4 | Assemblerroutine in den TIM4-Interrupt einbinden | UIRTim4=ON
UIRTIM5 | Assemblerroutine in den TIM5-Interrupt einbinden | UIRTim5=ON
UIRTOFL | Assemblerroutine in den TIMOFL-Interrupt einbinden | UIRTofl=ON
UIRTPM2C0 | Assemblerroutine in den TPM2CH0-Interrupt einbinden | UIRTpm2C0=ON
UIRTPM2C1 | Assemblerroutine in den TPM2CH1-Interrupt einbinden | UIRTpm2C1=ON
UIRTPM2OFL | Assemblerroutine in den TPM2OVF-Interrupt einbinden | UIRTpm2Ofl=ON
URILLTOK | Assemblerroutine bei einem illegalen Tokenbefehl starten | URIllTok=ON
URTOK | Assemblerroutine in den Interpreter einbinden | URTok=ON
Konfiguration
Schlüsselwort | Kurzbeschreibung | Beispiel
CONFIG1 | Erstes Konfigurationsregister der Open-Macro | PRINT CONFIG1
CONFIG2 | Zweites Konfigurationsregister der Open-Macro | CONFIG2=&b01000000
DCF77DIS | DCF77-Auswertung an FREQ1 deaktivieren | Dcf77Dis=ON
FREQ2 | Systemtakt auf der Open-Macro justieren (kalibrieren) | FREQ2=128
I2CDELAY | I²C-Bustakt konfigurieren | POKE i2cdelay,20
REALPOP | LIFO-Stackhandling aktivieren und Stacksichern deaktivieren | RealPop=ON
SLOWMODE | Controller in einen stromsparenden Modus versetzen | SLOWMODE ON
Betriebssystemstatus
Schlüsselwort | Kurzbeschreibung | Beispiel
CSTKPTR | Zeiger (Pointer) des Rechenstacks | PRINT CSTKPTR
FILECHG | Signalflag für Dateiveränderungen | PRINT FileChg
GSTKPTR | Zeiger (Pointer) des GOSUB-Stacks | PRINT GSTKPTR
IIARFND | Signalflag für existierende INLINE-Interrupt-Assemblerroutine | PRINT IiarFnd
IRQACT | Signalflag für Ausführung der BASIC-Interruptroutine | PRINT IrqAct
IRQREQ | Signalflag für Anforderung der BASIC-Interruptroutine | PRINT IrqReq
IRQSET | Signalflag für Vereinbarung der BASIC-Interruptroutine | PRINT IrqSet
PCADR | Programmzähler im Tokencode | PRINT PCADR
VERSION | Versionsnummer vom geladenen Betriebsystem abfragen | PRINT VERSION

## Softwaremodule für die OM

Um die Funktionalität der OM zu erhöhen, existieren viele Softwaremodule, die meist in INLINE-Assembler geschrieben wurden und so in jedes beliebige BASIC-Programm eingebunden werden können. Wie die Module im einzelnen zu benutzen sind, wird in den entsprechenden ZIP-Archiven erklärt. Die folgenden Erläuterungen sollen nur eine Übersicht über einige Softwaremodule vermitteln.

### Inter-Integrated-Circuit-Bus (I²C, IIC)

Das Softwaremodul stellt an den beiden Digitalports PORT[5] und PORT[6] der kleinen OM-Controller einen I²C-Bus mit 100 kHz Bustakt zur Verfügung. Außerdem wird in den beiliegenden Beispielprogrammen gezeigt, wie ein I²C-EEPROM, das Videotext-IC SAA5246AP/E und mittels PCF8574-Portexpander ein 4x20-LCD über den I²C-Bus angesprochen werden kann. Damit kann nun erstmals auch an der Open-Micro ein LCD mit hoher Geschwindigkeit betrieben werden und es muß nicht mehr der gesamte zweite Byteport der Open-Mini, -Midi oder -Macro belegt werden.
Bei der Open-Maxi steht der I²C-Bus an den eigens dafür vorgesehenen Ports SDA und SCL zur Verfügung. Die Routinen für I²C befinden sich bereits im Betriebssystem und können als Firmwareroutinen genutzt werden.
I²C ist ein von Philips in den frühen 80er Jahren entwickelter serieller Bus, der benutzt wird, um Integrierte Schaltkreise (ICs) mit geringer Übertragungsgeschwindigkeit zu verbinden. Daten lassen sich beliebig langsam über den Bus senden. Die Standardgeschwindigkeit beträgt 100 kBit/s, was einer Datenrate von ungefähr 10 Kilobyte pro Sekunde entspricht.
Der Bus besteht aus den drei Leitungen SDA, SCL und GND. SDA dient zur bidirektionalen Übermittlung von Adressen und Daten zwischen bis zu 256 verschiedenen Geräten am Bus. SCL ist die CLOCK-Leitung. Sie signalisiert, zu welchem Zeitpunkt SDA einen gültigen Zustand hat. Die Geräte am I²C-Bus werden in die Kategorien Master und Slave unterteilt. Der Master sorgt für das Takten der SCL-Leitung sowohl beim Senden als auch beim Empfangen von Daten zum, bzw. vom Slave.
Der Ruhezustand beim I²C-Bus ist auf beiden Leitungen HIGH-Potential (5 Volt). Das wird dadurch erreicht, indem die beiden Leitungen über Pullup-Widerstände mit 5 Volt verbunden sind. Wenn nach dem Ruhezustand SDA auf LOW (0 Volt) geht, während SCL weiter HIGH ist, ist das das Startsignal für die Datenübertragung. Danach wird in einem Byte (8 Bit) die Kennung des anzusprechenden Geräts am Bus beginnend mit dem MSB übertragen, indem SDA entsprechend dem Bit gesetzt, und anschließend mittels SCL ein kurzer LOW/HIGH/LOW-Impuls gesendet wird. Nach der Übertragung der 8 Bits deaktiviert der Sender die SDA-Leitung, damit der Empfänger auf dieser Leitung ein Acknowledge-Signal senden kann, indem SDA auf LOW gezogen wird. Fehlt das ACK-Signal ist der Empfänger entweder beschäftigt, oder - wenn der Empfänger ein Master ist - dem Sender wird signalisiert, daß das Senden von Daten beendet werden soll. Wenn mehr als ein Byte übertragen wird, folgen die nächsten 8 Bit direkt an das ACK-Signal (ohne neues Startsignal). Beendet wird die Übertragung, wenn im Anschluß an die ACK-Quittierung SDA auf HIGH geht, während SCL bereits HIGH ist. Somit ist dann wieder der Ausgangszustand erreicht.
Um verschiedene Geräte über den I²C-Bus ansprechen zu können, erhält jedes Gerät eine Kennung, bzw. Bus-Adresse. Ein Sender muß bei einer Übertragung mit dem START-Impuls und der Gerätekennung beginnen. Die ersten 4 Bit der Kennung geben den Schaltungstyp an. Dieser wird vom Hersteller vorgegeben. Bei einem I²C-EEPROM wie dem 24C256 ist die Kennung des Schaltungstyps dualkodiert 1010. Die folgenden 3 Bits (A2, A1 und A0) können mittels Verdrahtung an den Pins des EEPROMs gesetzt werden. Das achte Bit (R/W) gibt an, ob der Sender im folgenden Byte lesen (R/W ist HIGH) oder schreiben (R/W ist LOW) will. So ergibt sich eine Lesekennung für das serielle EEPROM von $a1 (dezimal 161) und eine Schreibkennung von $a0 (dezimal 160). Auf diese Art und Weise können bis zu acht EEPROMs am Bus betrieben werden, vorausgesetzt A2, A1 und A0 sind bei jedem EEPROM anders kodiert.
Das Bild zeigt den Anschluß des EEPROMs 24C256 an die OM. Das IC bietet 32 Kilobyte EEPROM zur permanenten Datenspeicherung. Die im Bild eingezeichneten Pull-Up-Widerstände R1 und R2 können bei der OM entfallen, da das Softwaremodul SCL im Push-Pull-Modus anspricht und an SDA der interne Pull-Up-Widerstand im Controller aktiv ist. Für größere Leitungslängen empfiehlt es sich aber, zusätzliche externe Widerstände bis hinunter zu 1 kOhm vorzusehen.

### I²C-LC-Display (I²C-LCD)

Die OM-Controller unterstützen das Ansprechen eines I²C-Liquid Crystal Displays (I²C-LC-Display, I²C-LCD, I²C-Flüssigkristallanzeige). Dazu muß ein normales Text-LCD (HD44780-kompatibel, Industriestandard) an einen I²C-Portexpander PCF8574 angeschlossen und der Portexpander mit dem I²C-Bus der OM verbunden werden.
Im Beispiel "Kleine Pizza-Uhr" befinden sich die aktuellsten Routinen für das I²C-LCD auf der Open-Macro. Die Ausgabe findet auf dem an BYTEPORT[2] angeschlossenen I2C-LCD von Conrad Electronic (Bestellnr. 198330) statt. Darüber hinaus wird gezeigt, wie auf dem LCD komfortabel Strings (also Texte) ausgegeben werden können. Als kleinen Bonus gibt es zwei weitere Programme, die ebenfalls das I2C-LCD nutzen.
Die Open-Maxi besitzt bereits in ihrem Betriebssystem Routinen für das I²C-LCD. Es wird daher komfortabel unterstützt. Es stehen die neuen Befehle LCDINIT, LCDCLS, LCDLOCATE, LCDCMD, LCDPUT und LCDPRINT zur Verfügung. Die I²C-Adresse des Portexpanders PCF8574 für das LCD ist änderbar. Dadurch wird das Ansprechen mehrerer LCDs ermöglicht. Die Hintergrundbeleuchtung oder 2. Enable-Leitung lassen sich vom Anwender setzen. Siehe Beispiel, Hinweis und Pinbelegung.

### Pulsweitenmodulation (PWM)

Mit dem PWM-Assemblermodul kann mit der Open-Macro ein pulsweitenmoduliertes Signal erzeugt werden. Die Open-Maxi bietet bereits von Haus die zwei PWM-Ports DA[1] und DA[2] an. Im Folgenden wird erklärt, was ein PWM-Signal ist und wozu es nützlich ist.
Bild a zeigt ein Rechtecksignal, bei dem das Tastverhältnis 1-zu-1 beträgt. Die Zeit, die das Signal auf 0 Volt (GND) liegt, ist also genauso groß wie die Zeit, während der das Signal auf 5 Volt (VDD) liegt. Beide Zeiten zusammenaddiert ergeben die Periodendauer des Signals. Und der Kehrwert der Periodendauer ist die Frequenz des Signals, gemessen in Schwingungen pro Sekunde oder Hertz (Hz).
In Bild b beträgt das Tastverhältnis nicht mehr 1:1, sondern ungefähr 1:3. Über größere Zeitabschnitte betrachtet ist das Signal also 25% der Zeit auf 5 Volt und 75% der Zeit auf 0 Volt. Und in Bild c ist das Tastverhältnis in etwa umgekehrt.
Signale, wie die im Bild gezeigten, lassen sich von einem Mikrocontroller meist sehr einfach erzeugen. Die Frequenz bleibt konstant und es wird nur das Tastverhältnis verändert. Man spricht von Pulsweitenmodulation (PWM). Wird ein pulsweitenmoduliertes Signal über einen größeren Zeitraum gemittelt, zum Beispiel mit Hilfe eines Tiefpaßfilters mit ausreichend geringer Grenzfrequenz, so ergibt sich eine Spannung am Ausgang des Filters, die proportional zum Tastverhältnis ist. In Bild a ist das Signal 50% der Zeit auf 5 Volt. Gemittelt ergibt sich also der Spannungswert 2,5 Volt. In Bild b ergeben sich 25% von 5 Volt, also 1,25 Volt. Und das Signal in Bild c würde zu einer Gleichspannung von 3,75 Volt.
Auf diese Weise erhält man einen sehr einfach aufzubauenden Digital-Analog-Umsetzer. Der Mikrocontroller kann hiermit jede beliebige Gleichspannung erzeugen. Falls die Frequenz des PWM-Signals ausreichend groß und die Grenzfrequenz des Tiefpaßfilters nicht zu niedrig gewählt wurde, lassen sich auch Wechselspannungen, z.B. Tonsignale, mit Hilfe des PWM-Signals erzeugen. Im Prinzip handelt es sich um einen 1-Bit-DA-Wandler.
Um ein PWM-Signal zu filtern, würde ein einfaches passives Tiefpaßfilter, bestehend aus einem Widerstand und einem Kondensator, ausreichen. Allerdings sind die damit erzielten Ergebnisse nicht optimal. Sinnvoller ist der Einsatz eines Tiefpaßfilters höherer Ordnung.
Der linke Operationsverstärker LM358, die Widerstände R2, R3 und R4 und die Kondensatoren C2, C3 und C4 bilden ein Tiefpaßfilter 3. Ordnung. Der rechte Operationsverstärker ist als nichtinvertierender Spannungsverstärker geschaltet, der mit R1 und R5 auf eine Verstärkung von 2 eingestellt wurde. Der Verstärker wirkt zugleich als Impedanzwandler. Zum Einsatz kam der LM358, da dieser Operationsverstärker mit einfacher Versorgungsspannung auskommt.
Die Bauteilwerte des Filters wurden experimentell ermittelt. Die Schaltung bietet eine gute Werteauflösung, aber eine schlechte Zeitauflösung. Das heißt, es dauert einige Zeit (rund 0,3 Sekunden), bis die Ausgangsspannung den gewünschten Spannungswert erreicht. Der Wert wird aber sehr präzise erreicht. Die Taktfrequenz des PWM-Signals wird sehr stark unterdrückt.
Für höhere Ansprüche kann man ein Filter nach einer bestimmten Filtercharakteristik entwerfen. In der Meßtechnik wird sehr häufig die Besselcharakteristik gewählt, da diese im Gegensatz zu Tschebyscheff und Butterworth nicht zum Überschwingen im Zeit- und/oder Frequenzbereich neigt, aber einen steileren Übergang vom Durchlaß- in den Sperrbereich bietet als ein passives Filter. Siehe "Halbleiter-Schaltungstechnik" von Tietze und Schenk.

### DCF77-Signalauswertung

Mit dem Zeitgesetz vom 25. Juli 1978 hat die Physikalisch-Technische Bundesanstalt (PTB) den Auftrag erhalten, für die Bundesrepublik Deutschland die Gesetzliche Zeit darzustellen und zu verbreiten. Zur Wahrnehmung der ersten Aufgabe benutzt das Labor "Zeiteinheit" der PTB Braunschweig vier Atomuhren, CS1 bis CS4, die zu den genausten Frequenznormalen gehören. Die Bezeichnung "CS" ist vom Cäsium abgeleitet, dessen Eigenschaften in den verwendeten Atomuhren genutzt werden. Zur Verbreitung der codierten Zeitinformation dient der Sender DCF77 in Mainflingen, etwa 30 km südöstlich von Frankfurt am Main. Er benutzt die Langwellenfrequenz 77,5 kHz, wodurch eine maximale Reichweite von 1000 bis 1500 km bei nur 30 kW Sendeleistung erreicht wird. Auf diese Weise kann das Zeitsignal zumindest nachts in ganz Mitteleuropa empfangen werden.
Mittels DCF-Modul (Conrad-Best.Nr. 641138) und DCF-Routinen läßt sich das Zeitsignal auch auf der Open-Macro nutzen und auswerten. Im Open-Maxi-Betriebssystem sind die Routinen bereits integriert. Es muß der invertierte Ausgang des Empfängermoduls verwendet werden. Selbstverständlich sollte man das Modul an einer stabilisierten Spannungsquelle (ohne Brumm) betreiben. Außerdem sollen einige verkaufte Module kein sauberes Signal ausgeben. Es soll helfen, einen 100-nF-Kondensator an den Ausgang gegen Masse zu schalten.
Tip zum Aufstellen des DCF77-Empfängermoduls: Die Stelle, die für den Empfänger vorgesehen ist, mit einem tragbaren Radio "abhören". Hört man an der Stelle Langwellensender (Langwelle von 150-285 kHz) ist schon fast sicher, daß man dort auch DCF77 empfangen kann. Durch Drehen um die Längsachse läßt sich hier die beste Stellung des Moduls finden. Vermeiden sollte man die Nähe von Lautsprechern, Monitoren, Fernsehern, Computern und schaltenden Relais. In der Nähe von Fenstern hat man dagegen meistens einen guten Empfang. Falls es tagsüber trotzdem nicht klappt, sollte man es einmal nachts versuchen. Und falls es immer noch nicht kappt, kann es daran liegen, daß der DCF77-Sender augenblicklich gewartet wird. Das geschieht etwa 20 mal pro Monat und in der Zeit wird der Sender für 2 bis 10 Minuten abgeschaltet.

### Extended Ports

Ein Nachteil der kleinen OM-Controller war bisher deren relativ geringe Portanzahl. Aus diesem Grund lassen sie sich jetzt mit diesem Softwaremodul um bis zu 64 Extended Ports erweitern. Die Extended Ports werden mittels PCF8574-I2C-Portexpandern realisiert und lassen sich in BASIC nach der Aktivierung des Softwaremoduls genauso wie die normalen Ports ansprechen.
Auf der Open-Maxi befinden sich die Softwareroutinen für acht Portexpander bereits im Betriebssystem und da sich die Open-Maxi die Ausgabe merkt, lassen sich sogar einige Pins eines PCF8574 als Input und andere als Output verwenden.
Über die drei Pins A0, A1 und A2 am PCF8574 werden die acht Portexpander unterschieden. Das heißt, bei jedem der acht Portexpander müssen diese drei Pins anders beschaltet werden.

### Modellbau-Servos

Mit dem Servo-Assemblermodul ist es möglich, Modellbau-Servos (positiver Impuls) mit der OM anzusteuern. Bei den kleinen OM-Controllern kann man den Servo-Impuls an jedem Port außer PORT[3] erzeugen. Außerdem wurde auf einen großen Stellwinkel (erweiterter Stellbereich) Wert gelegt, um das Potential des Servos voll auszuschöpfen.
Wenn man den Servo an der gleichen Stromquelle wie die OM betreibt, dann ist darauf zu achten, daß die Stromquelle einen ausreichenden Strom zur Verfügung stellen kann. Denn sonst liefert die OM keine sauberen Impulse und der Servo fährt die vorgesehene Position nicht an.

### 8 MHz Bustakt

Der Bustakt der Open-Macro wird von 3.2 MHz auf 8 MHz erhöht. Die OM wird also genauso schnell getaktet wie die C-Control I UNIT M 2.0. Da die OM oft nur mit Bytevariablen arbeiten muß, schneidet sie in Benchmark-Tests deutlich schneller ab als die neue C-Control. Es kann im laufenden Betrieb zwischen 3.2 und 8 MHz hin- und hergewechselt werden.
Es wird ein Quarzoszillator im DIP-14-Gehäuse verwendet, den Reichelt unter der Artikelnummer "OSZI 32,000000" für 0,86 EUR anbietet. Auch ein SMD-Quarzoszillator läßt sich verwenden. Dieser hat eine Größe von nur 3,2 x 2,5 mm, ist aber für eine Lastkapazität von nur 15 pF ausgelegt.

### Erweiterte Zahlenformate

Für 32-Bit-Ganzzahl-Arithmetik existiert ein in Assembler erstelltes Softwaremodul. Es bietet hohe Verarbeitungsgeschwindigkeit, vorzeichenbehaftete Zahlen und ein schnelles PRINT32. Es ist zu allen OM-Controllern kompatibel.
Für die Open-Macro und Open-Maxi gibt es ein Softwaremodul für 32-Bit-Fließkommazahlen ("Gleitkommazahlen") im IEEE-Format. Es verwendet die Float-Routinen für 6805 von Motorola. Der Darstellungsbereich umfaßt ±1,175*10-38 bis ±3,403*1038 bei etwa 7 dezimalen Stellen. Ganzzahlige, vorzeichenbehaftete 16-Bit-Zahlen lassen sich leicht ins Fließkommazahlen-Format konvertieren. Ebenso leicht ist die Rückkonvertierung möglich.
Für die Open-Maxi steht eine komfortable 32-Bit-Arithmetikerweiterung zur Verfügung.

### Weitere Softwaremodule

Weitere Softwaremodule und Beispielprogramme befinden sich auf der offiziellen OM-Infosite. Sie wird laufend erweitert. Die "Neuigkeiten"-Seite sollte regelmäßig besucht werden.

## Beschaltung der Ports

In den nachfolgenden Beispielen wird beschrieben, wie man die Eingangs- und Ausgangsports der OM-Controller beschalten kann. Da es sehr viele Möglichkeiten zur Beschaltung gibt, soll nur ein kleiner Einblick in die Grundlagen vermittelt werden.

### Beschaltung von Eingangsports

Bild 1
In diesem Beispiel führt der Port ein "High"-Signal (5 Volt, ON), wenn der Schalter offen ist. Wird der Schalter geschlossen, wird am Port ein "Low"-Signal (0 Volt, OFF) erkannt. Da die OM interne Pull-Up-Widerstände besitzt, läßt sich der Widerstand R1 meist einsparen.
Bild 2
Ist genau das gleiche wie in Bild 1, nur invertiert. Bei einem offenen Schalter wird ein "Low"-Signal (OFF) erkannt. Damit die internen Pull-Up-Widerstände der OM das Meßergebnis nicht verfälschen, sollten sie deaktiviert werden (siehe PULLUPA und PULLUPB).
Bild 3
Hier wird ein Optokoppler zur galvanischen Trennung verwendet. Damit können Spannungen, die größer als 5 Volt sind, oder auf ungünstigem Potential liegen mit der OM detektiert werden.
Bild 4
Diese Schaltung basiert auf dem Prinzip des Spannungsteilers. Durch die Reihenschaltung der Widerstände wird die Spannung herabgesetzt. In diesem Beispiel können so Gleichspannungen bis 16 Volt gemessen werden. Das Spannungsverhältnis wird durch die beiden Widerstände festgelegt und beträgt rund 3/(6,8+3)=0,3. Bei 16 Volt liegen also etwa 16*0.3=4,9 Volt am Ausgang.
Bild 5
Hier wird das Signal eines KTY10 (Temperatursensor) ausgewertet. Wie in Bild 4 basiert diese Schaltung auf einem Spannungsteiler. Ändert sich die Temperatur, so ändert sich auch der Widerstand vom KTY10. Die gemessene Spannung läßt sich mit Hilfe einer Tabelle (siehe LOOKTAB) linearisieren.

### Beschaltung von Ausgangsports

Bild 1
Hier wird eine LED über einen Vorwiderstand direkt an einem Port betrieben. Die Ports der OM können maximal 10 mA schalten. Ist der Port "high", dann ist die LED an. Ist der Port "low", dann ist die LED aus. Sogenannte Low-Current-LEDs kommen mit weniger Strom aus und der Widerstand R1 läßt sich dann vergrößern.
Bild 2
Um die Schaltleistung zu verstärken kann man einen Transistor verwenden. Je nach Type lassen sich so mehrere Ampere schalten. Bei diesem Beispiel mit PNP-Transistor ist die Lampe aus, wenn der Port "high" ist.
Bild 3
Mit dieser Schaltung wird gezeigt, wie ein Relais angeschlossen werden kann. Durch die Verwendung eines Relais erhält man gleichzeitig eine galvanische Trennung. So können Geräte geschaltet werden die eine größere Spannung haben. Die Freilaufdiode D1 ist unbedingt erforderlich, da der Transistor oder der Controller sonst zerstört werden könnte.
Bild 4
Der ULN2803 besteht aus mehreren Transistoren. Mit diesem Schaltkreis können 8 Ports verstärkt werden. Wenn mehrere Ausgänge verwendet werden, dann ist das IC eine gute Alternative zu Transistoren. Die maximale Strombelastbarkeit liegt bei 1 Ampere.
Bild 5
Bei einigen Anwendungen ist eine galvanische Trennung zwingend notwendig, ohne daß man eine große Schaltleistung benötigt. Dafür kann man auch einen Optokoppler verwenden.
Bild 6
Ein Solid-State-Relais ist ein elektronisches Relais. Es verfügt auch über eine galvanische Trennung. Allerdings besitzen Solid-State-Relais keine Mechanik und können daher schneller schalten und sie haben keine Verschleißteile, was eine hohe Lebensdauer garantiert.

## Pinbelegung der Open-Control M-Unit

Hier die ausführliche Auflistung aller Pins des AW60-Controllers und ob sie bei der Open-Control M-Unit-Hardware, auf der die Open-Maxi basiert, an einer Standard-Stiftleiste liegt, die bereits die C-Control 1.1 M-Unit zur Verfügung stellte, oder aber an einer neuen Stiftleiste.

Pin am AW60- Controller | Pin-Bezeichnung laut Freescale | Auf Standard- Stiftleiste oder neue Stiftleiste | Pinfunktion im Open-Maxi-Betriebssystem (Funktion in Klammern wird nicht vom OS bereitgestellt) | Alternative oder optionale Pinfunktion (Funktion in Klammern wird nicht vom OS bereitgestellt)
26 | PTA0 | standard | PORT[1] |
27 | PTA1 | standard | PORT[2] |
28 | PTA2 | standard | PORT[3] |
29 | PTA3 | standard | PORT[4] |
30 | PTA4 | standard | PORT[5] |
31 | PTA5 | standard | PORT[6] |
32 | PTA6 | standard | PORT[7] |
33 | PTA7 | standard | PORT[8] |
34 | PTB0/AD1P0 | standard | PORT[9] | AD[9]
35 | PTB1/AD1P1 | standard | PORT[10] | AD[10]
36 | PTB2/AD1P2 | standard | PORT[11] | AD[11]
37 | PTB3/AD1P3 | standard | PORT[12] | AD[12]
38 | PTB4/AD1P4 | standard | PORT[13] | AD[13]
39 | PTB5/AD1P5 | standard | PORT[14] | AD[14]
40 | PTB6/AD1P6 | standard | PORT[15] | AD[15]
41 | PTB7/AD1P7 | standard | PORT[16] | AD[16]
60 | PTC0/SCL1 | standard | SCL | PORT[17]
61 | PTC1/SDA1 | standard | SDA | PORT[18]
62 | PTC2/MCLK | neu | (MCLK) | PORT[19]
63 | PTC3/TxD2 | standard | TXD | PORT[20]
01 | PTC4 | neu | RTS | PORT[21]
64 | PTC5/RxD2 | standard | RXD | PORT[22]
09 | PTC6 | neu | CTS | PORT[23]
42 | PTD0/AD1P8 | standard | AD[1] | PORT[25]
43 | PTD1/AD1P9 | standard | AD[2] | PORT[26]
46 | PTD2/KBI1P5/AD1P10 | standard | AD[3] | PORT[27]
47 | PTD3/KBI1P6/AD1P11 | standard | AD[4] | PORT[28]
50 | PTD4/TPM2CLK/AD1P12 | standard | AD[5] | PORT[29]
51 | PTD5/AD1P13 | standard | AD[6] | PORT[30]
52 | PTD6/TPM1CLK/AD1P14 | standard | AD[7] | PORT[31]
53 | PTD7/KBI1P7/AD1P15 | standard | AD[8] | PORT[32]
13 | PTE0/TxD1 | neu | PORT[33] | (TXD2)
14 | PTE1/RxD1 | neu | PORT[34] | (RXD2)
15 | PTE2/TPM1CH0 | neu | PORT[35] | (SERVO1)
16 | PTE3/TPM1CH1 | neu | PORT[36] | (SERVO2)
17 | PTE4/SS1 | neu | PORT[37] | (SS)
18 | PTE5/MISO1 | neu | PORT[38] | (MISO)
19 | PTE6/MOSI1 | neu | PORT[39] | (MOSI)
20 | PTE7/SPSCK1 | neu | PORT[40] | (SPSCK)
04 | PTF0/TPM1CH2 | standard | BEEP | PORT[41]
05 | PTF1/TPM1CH3 | standard | TEST | PORT[42]
06 | PTF2/TPM1CH4 | standard | FREQ1 | PORT[43]
07 | PTF3/TPM1CH5 | standard | FREQ2 | PORT[44]
08 | PTF4/TPM2CH0 | standard | DA[1] | PORT[45]
11 | PTF5/TPM2CH1 | standard | DA[2] | PORT[46]
12 | PTF6 | neu | (RTS2) | PORT[47]
10 | PTF7 | neu | (CTS2) | PORT[48]
23 | PTG0/KBI1P0 | standard | START | PORT[49]
24 | PTG1/KBI1P1 | neu | RUN-LED | PORT[50]
25 | PTG2/KBI1P2 | neu | ACTIVE-LED | PORT[51]
48 | PTG3/KBI1P3 | neu | DCFOK-LED | PORT[52]
49 | PTG4/KBI1P4 | neu | (KEYB) | PORT[53]
57 | PTG5/XTAL | --- | XTAL | PORT[54]
58 | PTG6/EXTAL | --- | EXTAL | PORT[55]
03 | RESET | standard | RESET |
02 | IRQ | standard | IRQ |
56 | BKGD/MS | neu | BKGD |
22 | VDD | standard | VDD |
21 | VSS | standard | GND |
59 | VSS | standard | GND |
44 | VDDAD | neu | VDDAD |
45 | VSSAD | --- | GND |
54 | VREFH | standard | UREF |
55 | VREFL | --- | GND |

## Tips und Tricks

### Die ConTEXT-Entwicklungsumgebung

Um ein BASIC-Programm komfortabel zu erstellen und auf die OM zu übertragen, benötigt man eine sogenannte integrierte Entwicklungsumgebung (IDE). Eine Entwicklungsumgebung besteht aus mehreren Tools, die aufeinander abgestimmt werden müssen. Bei vielen Anwendern ist die Entwicklungsumgebung ConTEXT sehr beliebt. ConTEXT enthält unter anderem einen komfortablen Programm-Editor zum Erstellen der BASIC-Programme. Das Tool kann auf der Internetseite http://www.contexteditor.org kostenlos heruntergeladen werden. Da ConTEXT aber nur den Editor bereitstellt, benötigt man noch einen BASIC-Compiler und ein Übertragungstool ("Downloadtool") um das erstellte und übersetzte BASIC-Programm auf die OM zu laden. Als BASIC-Compiler wird am sinnvollsten der eigens für die OM entwickelte Open-Control/BASIC-Compiler (OCBAS.EXE) von Dietmar Harlos verwendet. Als Übertragungstool hat sich unter Windows besonders OMDLWIN bewährt. Beide Programme können bei den Downloads heruntergeladen werden. OMDLWIN läßt sich komfortabel in die ConTEXT-IDE einbinden, auf Tastendruck starten und kann den OM-Controller nach einer erfolgreichen Übertragung automatisch starten. ZIP-Archive lassen sich übrigens mittels WinZip entpacken.
Bevor man mit der Programmierung der OM beginnen kann, muß man aber erst noch diese Tools aufeinander abstimmen. Außerdem ist es sinnvoll, noch ein Terminal-Programm mit in die Programmierumgebung einzubinden. Mit dem Terminal-Programm kann man sich dann die Daten anschauen, die von der OM über die Serielle Schnittstelle per PRINT oder PUT gesendet werden. Man kann damit auch Zeichen und Texte über die PC-Tastatur eingeben und zur OM senden. In der Betatestphase hat sich das Terminal-Programm für die C-Control von Dietmar Harlos (TERMINAL.EXE oder Terminal32.exe) hervorragend bewährt. Das Terminal-Programm liegt dem ZIP-Archiv mit den Übertragungstools bei. Terminal32.exe sollte unter neueren Windowsversionen verwendet werden.
Nachfolgend wird detailliert beschrieben, wie solch eine Konfiguration aussehen kann.
Zuerst erstellt man auf Laufwerk C: ein Verzeichnis mit dem Namen OM-Tools. Es läßt sich also über den Pfad C:\OM-Tools ansprechen. In dieses Verzeichnis wird nun der BASIC-Compiler OCBAS.EXE, der BASIC-Compiler OCBAS32.EXE, das Übertragungstool OMDLWIN.EXE und das Terminal-Programm TERMINAL.EXE oder Terminal32.exe hineinkopiert. Es befinden sich also nach dem Kopieren die vier Dateien in dem Verzeichnis C:\OM-Tools. Selbstverständlich ist es auch möglich, die Hilfsprogramme in einem anderen Verzeichnis abzulegen. Dann müssen in der folgenden Anleitung allerdings die Pfade zu den Dateien angepaßt werden.
Jetzt wird ConTEXT in der deutschen Version installiert. Dabei wird immer den Anweisungen gefolgt, bis die Installation abgeschlossen ist. Nach der Installation sollte sich ein ConTEXT-Icon auf dem Desktop befinden. Damit ist die halbe Arbeit bereits getan und die Programme müssen nur noch aufeinander abgestimmt werden.
Dazu startet man jetzt ConTEXT und geht auf den Menüpunkt Einstellungen. Danach auf den Menüpunkt Umgebungseinstellungen. Dann wechselt man auf Benutzerbefehle. Jetzt werden die Einstellungen der einzelnen Tools festgelegt. Dazu ruft man Neu auf. Es öffnet sich ein neues Fenster in dem jetzt bas eingefügt und dann auf OK geklickt wird. Jetzt wird als Benutzerbefehl bas mit den Zweigen F9, F10, F11, F12 angezeigt.
Man klickt jetzt einfach auf F9 und kann dann Angaben zum Tool machen, das starten soll, wenn die Taste F9 in ConTEXT gedrückt wird. Wir belegen jetzt F9 mit dem BASIC-Compiler. Bei Ausführen wird jetzt C:\OM-Tools\OCBAS32.EXE eingegeben. Bei Start in ein %p (das p unbedingt klein schreiben). Bei Parameter wird ein %n -withfilename eingetragen. Bei Fenster wird Normal ausgewählt. Bei Hinweis wird BASIC-Compiler eingetragen und bei Speichern wird aktuelle Datei eingetragen. Jetzt folgen noch ein paar Häkchen und der BASIC-Compiler ist fertig eingerichtet. Bei Benutze kurze DOS-Dateinamen, bei Konsolenausgabe aufzeichnen und bei Konsolenausgabe zur letzten Zeile scrollen wird ein Häkchen gesetzt. Bei Regel für Compiler-Ausgabe wird %n(%l) eingetragen. Damit sind wir fertig. Diese Einstellungen werden erst einmal mit Übernehmen abgespeichert.
Jetzt klickt man auf F10 und gibt die Parameter des Übertragungstools ein. Bei Ausführen wird C:\OM-Tools\OMDLWIN.EXE eingegeben. Bei Start in ein %p (das p unbedingt klein schreiben). Bei Parameter wird %F.DAT COM1 autobaud autostart (das F unbedingt groß schreiben, kein Leerzeichen zwischen %F und .DAT) eingetragen. Das COM1 bezieht sich auf die erste Serielle Schnittstelle. Wird die OM an einem anderen COM-Port angeschlossen, so muß natürlich der entsprechende COM-Port eingetragen werden (COM2, COM3, COM4 oder andere). Es existieren Konverter, die USB nach RS232 wandeln können. Damit läßt sich die OM auch über USB programmieren. In diesem Fall muß der virtuelle COM-Port des Treibers eingetragen werden. Durch das "autostart" wird der OM-Controller nach einer erfolgreichen Programmübertragung automatisch gestartet. Durch "autobaud" wird automatisch die maximal mögliche Übertragungsgeschwindigkeit gewählt. Das ist nützlich auf der Open-Macro und Open-Maxi. Bei Fenster wird wieder Normal ausgewählt und bei Hinweis wird DAT übertragen eingetragen. Bei Benutze kurze DOS-Dateinamen wird ein Häkchen gesetzt. In den anderen Feldern wird wieder nichts eingetragen. Diese Einstellungen werden mit Übernehmen gespeichert.
Jetzt klickt man auf F11 und trägt das Terminal-Programm ein. Bei Ausführen wird C:\OM-Tools\TERMINAL.EXE oder C:\OM-Tools\Terminal32.exe eingegeben. Bei Fenster wird Normal ausgewählt und bei Hinweis wird Terminal starten eingetragen. In den anderen Feldern wird wieder nichts eingetragen und es werden auch keine Häkchen gesetzt. Die Einstellungen werden jetzt mit Übernehmen gespeichert und danach wird die Umgebungseinstellung mit OK verlassen.
ConTEXT ist jetzt konfiguriert und es können BASIC-Programme editiert, compiliert und auf die OM geladen werden. Wer im externen Assembler AS05 programmieren möchte, kann diese Einstellungen natürlich auch für den Assembler AS05.EXE vornehmen. Dazu bei den Benutzerbefehlen wieder Neu aufrufen und die neue Gruppe asm anlegen. Sinnvollerweise legt man den Assembler auf die Taste F9. Als Parameter sollte -sl %n eingetragen werden. Auf die beschriebene Weise können natürlich auch andere Programme in ConTEXT eingebunden werden, die den Umgang mit der OM erleichtern. Zum Beispiel das Hilfsprogramm zum Starten der OM über die Serielle Schnittstelle.
Um ein Programm in die Open-Macro zu laden muß der Schalter auf dem PE-Board in Stellung Host stehen. Danach wird die Versorgungsspannung eingeschaltet und der Schalter sinnvollerweise auf Run zurückgestellt. Bei der Open-Maxi geht man folgendermaßen vor: Den AUTOSTART-Jumper nicht setzen und die Betriebsspannung anlegen. Zuerst sollte man ein Demo-Programm auf die OM laden, um sich zu vergewissern, daß die vorgenommenen Einstellungen korrekt sind. Dazu eignet sich gut die Datei MICRO_BM.BAS aus dem ZIP-Archiv mit den diversen Beispielen. Dazu öffnet man die Datei MICRO_BM.BAS in ConTEXT. Unmittelbar nach dem Öffnen wird der Quellcode der Datei im Editor angezeigt, den man mit den üblichen Editierkommandos verändern könnte.
Oberhalb im Menü sind 4 kleine Köpfe (Benutzerbefehle) abgebildet. Bewegt man den Mauszeiger über den ersten Kopf so wird BASIC-Compiler (F9) angezeigt. Sobald man ihn anklickt, wird eine Datei namens MICRO_BM.DAT erzeugt. Sie enthält den fertig übersetzten sogenannten Tokencode. Falls Fehler im Quellcode enthalten sein sollten, dann wird das im unteren Teil (in der Konsolenausgabe) von ConTEXT angezeigt und die DAT-Datei nicht erstellt. Durch Doppelklicken auf die Fehlermeldung springt der Cursor zur Zeile mit dem Fehler in der Quellcodedatei. Danach klickt man auf den zweiten Kopf bei dem DAT übertragen (F10) angezeigt wird. Jetzt wird die Datei MICRO_BM.DAT auf die OM geladen. Es muß also immer zuerst die BAS-Datei in eine DAT-Datei compiliert und diese dann übertragen werden. Nachdem die Datei erfolgreich übertragen wurde, wird jetzt der dritte Kopf bei dem Terminal starten angezeigt wird, angeklickt. Es öffnet sich das Terminal-Programm in einem Fenster. Falls das Programm in der OM noch nicht per OMDLWIN und "autostart" gestartet wurde, kann es durch den Reset-Knopf auf dem PE-Board oder durch Drücken der Eingabetaste (auch Enter oder Return genannt) im Terminal-Fenster gestartet werden. Wenn alles ordnungsgemäß funktioniert, dann wird im Terminal-Programm jetzt immer wieder Ergebnis: 10480 I/s (Open-Macro) angezeigt. Wenn man genug davon hat, kann man den Controller ausstellen und das Terminal-Programm durch Drücken auf die Taste ESC beenden.
Auf der Open-Maxi gilt: Während der Anwender sein Programm entwickelt, sollte der AUTOSTART-Jumper nicht gesetzt werden. Das ist auch nicht notwendig, denn die Open-Maxi wird durch das Downloadtool OMDLWIN oder durch Drücken der Eingabetaste (auch Enter oder Return genannt) im Terminal gestartet. Wenn das Programm fertig entwickelt ist, kann der AUTOSTART-Jumper gesetzt werden. Er wird von der Open-Maxi nur einmal nach RESET und nach jedem END abgefragt. Also nicht wie auf der C-Control I Version 1.1 ständig in der Idleloop, bzw. im Hostmode. Mittels "End2Host=ON : END" kann der Anwender wie bei den bisherigen OM-Controllern auch bei gesetztem AUTOSTART-Jumper in den Hostmode gelangen und ein neues Programm in die Open-Maxi übertragen.
Im Menüpunkt Einstellungen gibt es den Eintrag Einstellungen exportieren (Registry), mit dem man die oben vorgenommenen Einstellungen sichern kann. Damit stehen diese Einstellungen für eine Neuinstallation von ConTEXT zur Verfügung.

### Schneller Programmdownload

Es existiert ein Downloadtool namens OMDLWIN.EXE, das speziell für die OM-Controller entwickelt wurde und unter Windows läuft. Ab Version 1.3 dieses Downloadtools unterstützt es den neuen Parameter "AUTOBAUD", der statt der Baudrate angegeben werden kann, und auf der Open-Macro die schnellstmögliche Baudrate automatisch wählt, falls die Hardware-RS232 (ESCI) aktiviert ist. Mit ESCI und AUTOBAUD werden Programme bis zu zehnmal schneller übertragen! Im ZIP-Archiv, in dem sich OMDLWIN.EXE ab Version 1.3 befindet, existiert auch die INFO.TXT-Datei. Hier wird beschrieben, auf welche Weise der Anwender das ESCI der Open-Macro für den Programmdownload aktivieren kann.
Die Open-Maxi bietet komfortablen Programmdownload mit bis zu 115200 Baud an der Standard-Schnittstelle. Ab OMDLWIN.EXE Version 1.4 wird damit ein 58782 Byte großes Programm in 12 Sekunden übertragen. Um diesen schnellen Download zu aktivieren, muß ebenfalls der Parameter "AUTOBAUD" verwendet werden.

### Die Adreßaufteilung

Beim QB8-Controller reicht der Flash-Speicher von Adresse $de00 bis einschließlich $fdff. Er hat also mit 8192 Byte die doppelte Größe wie auf dem QT4/QY4. Der Speicher wird in Flash-Pages mit 64 Byte Größe verwaltet. Das Betriebssystem der Open-Macro reicht von Adresse $de00 bis einschließlich $e8bf und belegt somit 2752 Byte. Der Zeiger mit der Startadresse der Datendatei steht direkt hinter dem Betriebssystem auf $e8c0 und der Tokencode beginnt bei $e8c2. Falls ein Assemblermodul mit SYSCODE in den BASIC-Sourcecode eingebunden wird, belegt es wie auf den anderen kleinen OM-Controllern die letzten 256 Byte des Flash-Speichers ab Adresse $fd00.
Beim AW60-Controller reicht der Flash-Speicher von Adresse $0870 bis einschließlich $17ff und von $1860 bis einschließlich $ffff. Er hat also mit 63280 Byte eine beachtliche Größe. Der Speicher wird in Flash-Pages mit 512 Byte Größe verwaltet. Das Betriebssystem der Open-Maxi reicht von Adresse $0a00 bis einschließlich $17ff und von $fe00 bis $ffff und belegt somit 4096 Byte. Übrigens hat der Sourcecode des Betriebssystems 5329 Zeilen. (Zum Vergleich: Open-Micro und Open-Mini: 2483 Zeilen, Open-Midi: 2597 Zeilen, Open-Macro: 3848 Zeilen.) Die Länge der Tokendatei steht auf $1860 und der Tokencode beginnt bei $1862. Falls ein Assemblermodul mit SYSCODE in den BASIC-Sourcecode eingebunden wird, belegt es 400 Byte des Flash-Speichers und beginnt auf Adresse $0900.

### Informationen in der Definitionsdatei

Es lohnt sich besonders für fortgeschrittene Anwender, auch einmal einen Blick in die Definitionsdatei der verschiedenen OM-Controller zu werfen. Die jeweils aktuelle Datei kann auf der offiziellen Informationssite heruntergeladen werden. Die Definitionsdatei für die Open-Macro trägt den Namen OMAC.DEF und die zur Open-Maxi passende heißt OMAX.DEF. Die Datei enthält die unbedingt notwendigen Definitionen für die neuen internen Variablen zum Konfigurieren des Betriebssystems, zur Statusabfrage und zum Einbinden der User-Interruptroutine in verschiedene Interrupts. Außerdem sind am Ende der Datei die Definitionen für den integrierten Assembler aufgeführt, um auf alle Register der Controller-Module zugreifen zu können. Damit lassen sich alle vom Controller bereitgestellten Funktionen nutzen. Die Informationen in der Datei beschränken sich jedoch nicht nur auf reine Definitionen, sondern es wurden auch viele nützliche Bemerkungen und Hinweise eingefügt.

### Die Firmwareroutinen

Die Betriebssysteme der OM-Controller stellen bis zu 15 nützliche Firmwareroutinen zur Verfügung, die der Anwender in eigenen Assemblerprogrammen benutzen kann. Dazu muß die Datei OM_FW.PRO mittels INCLUDE eingebunden werden. In der Datei sind die diversen Firmwareroutinen ausführlich beschrieben. Die jeweils aktuelle Datei kann auf der offiziellen Informationssite heruntergeladen werden.

### Dauerhafte Datenspeicherung an fester Adresse

Manchmal ist es auf der Open-Macro wünschenswert, Daten dauerhaft zu speichern. Dafür können normalerweise die Dateifunktionen verwendet werden. Allerdings werden die Daten in der Datei gelöscht, sobald ein neues Programm in den Controller geladen wird. Außerdem werden sie immer im Flash-Speicher auf der ersten Seite (Page) hinter dem BASIC-Programm abgelegt. Die Adresse ist also abhängig von der Größe des BASIC-Programms.
Durch Umbiegen des Dateizeigers FILEPOS ist es allerdings möglich, jede beliebige Adresse des Flash-Speichers auszulesen und zu beschreiben. Der Flash-Speicher läßt sich aber nur pageweise löschen. Dieser Löschvorgang wird von den Dateifunktionen nur dann automatisch durchgeführt, wenn auf den Beginn einer Page geschrieben wird.
Das jeweils erste Byte einer jeden Flash-Page steht an Adresse $xx00, $xx40, $xx80 und $xxc0. Wenn ein SYSCODE-Assemblermodul vorhanden ist und nicht überschrieben werden darf, dann könnte man Daten auf der Flash-Page vor dem Assemblermodul, auf Adresse $fcc0 abspeichern. Wenn kein SYSCODE-Assemblermodul vorhanden ist oder es eine Größe von 192 Byte oder weniger hat, dann könnte man die Flash-Page $fdc0 benutzen. Auf diese Weise werden bis zu 64 Byte Daten jeweils am Ende des nutzbaren Flash-Speichers abgelegt.
Auf der Open-Maxi müssen keine solchen Tricks angewandt werden, da die Daten in der 32 kB großen I²C-EEPROM-Datei nicht durch das Übertragen eines Programms gelöscht werden.

##### Beispiel

`INCLUDE "omac.def"
FileByte=ON 'PRINT# und INPUT# im Byte- statt Wordformat
FILEPOS=&hfdc0 'vier Bytes auf Adresse $fdc0 speichern
PRINT# 3 'Das erste PRINT# schreibt auf das erste Byte der
PRINT# 255 'Flash-Page und führt deshalb zum Löschen der
PRINT# 123 'gesamten Page. Mit jedem Löschvorgang wird eine
PRINT# 98 'von 10.000 Schreib/Lösch-Zyklen verbraucht.
...
FILEPOS=&hfdc0 'vier Bytes von Adresse $fdc0 lesen
PRINT INPUT# 'Lesen geht beliebig oft, aber löschen läßt sich
PRINT INPUT# 'jede Flash-Page laut Angaben des Controller-
PRINT INPUT# 'herstellers "nur" 10.000 mal.
INPUT# a`

### Besonderheiten der Controller

Der Controller, auf dem die Open-Maxi basiert, enthält leider einen Fehler, den Freescale (heute NXP) verschuldet hat: Der Oszillator soll laut den Angaben von Freescale unterhalb von 0 °C nicht mehr zuverlässig funktionieren. Der "Internal Clock Generator" des AW60s ist sehr komplex, deshalb gibt mehrere Möglichkeiten, diesen Fehler zu umgehen. Die sinnvollste Methode ist, das Bit "High Gain Oscillator Select" (HGO) zu aktivieren. Dadurch benötigt der Controller laut meinen Messungen allerdings rund 3 mA mehr Strom. Auf der offiziellen OM-Infosite kann das Programm NVCONFIG.BAS ("Konfiguration der Open-Maxi") heruntergeladen werden, mit dem sich das Betriebssystem der Open-Maxi dauerhaft umkonfiguriert läßt und so auch eine Verwendung bei Minusgraden erlaubt.
Bei der Open-Maxi sollte man vorsichtig sein mit zu hoher Betriebsspannung: Laut Freescale beträgt die absolut maximale Betriebsspannung (VDD) des AW60s nur 5.8 Volt. Über diesem Wert kann der Controller zerstört werden. Beim QT4, QY4 und QB8 lag dieser Wert bei 6.0 Volt.
Die Stromaufnahme des AW60s bei einem Bustakt von 20 MHz beträgt typisch 16.8 mA bei 5 Volt. Es macht also Sinn, einen niedrigeren Takt zu benutzen. Das geht zum Beispiel mit SLOWMODE ON sehr komfortabel.
Die AD-Ports AD[1] bis AD[8] liegen bei der Open-Maxi genauso wie bei der C-Control I Version 1.1 standardmäßig in der Luft, was ungünstig ist. Wenn der Anwender nicht alle AD-Ports benötigt, sollte er die nicht verwendeten auf festes Potential legen. Sie können zum Beispiel auf I/O-Port-Funktion umgeschaltet und die internen Pull-Up-Widerstände aktiviert werden.
Auf der Open-Maxi ist das LVD-Modul auf 5 Volt konfiguriert. Messungen zeigten, daß der AW60-Controller bei 4.25 Volt Betriebsspannung stehenbleibt und bei 4.35 Volt wieder anfängt zu laufen.
Die C-Control I Version 1.1 setzt bei HANDSHAKE OFF die RTS-Leitung auf low. Das passiert bei der Open-Maxi erst, wenn versucht wird, Daten von der Seriellen Schnittstelle zu holen.
Die LED-Ports werden vom Open-Maxi-Betriebssystem nach einem Reset auf Ausgang geschaltet. Die ACTIVE-LED wird bei Programmstart eingeschaltet und bei Programmende ausgeschaltet. Die RUN-LED genauso, allerdings verlischt sie während PAUSE. Die DCF-OK-LED wird vom DCF77-Interrupt an- und ausgeschaltet. Er kann vom Anwender mit "Dcf77Dis=ON" deaktiviert werden.
Open-Maxi: Direkt nach Systemstart arbeitet der AW60 laut meinen Messungen mit stabilen 20 MHz Bustakt, die mittels 4 MHz Quarz erzeugt werden. Wenn man nun aber den Oszillator streßt, indem man den EXTAL-Pin über einen niederohmigen Widerstand auf Masse zieht, setzt der Takt aus. Der Controller bleibt aber nicht einfach stehen, sondern wird durch eine Art "Not-Taktung" weiterhin intern getaktet. Aber dadurch fängt der Bustakt an, in einem Bereich von +/- 0.1% zu pendeln und bleibt in diesem Zustand bis zum nächsten Reset oder bis das Anwenderprogramm wieder auf den externen Takt umschaltet. Dieser Wert liegt völlig in den Spezifikationen, denn Freescale gibt im Anhang des Manuals einen CJitter von max. 0.2% an. Es ist also beim AW60 völlig normal, daß der Bustakt in einem gewissen Frequenzbereich hin- und herpendelt. Das liegt daran, daß der Takt per FLL ("frequency-locked loop") generiert wird.
Das IIC-Modul vom AW60 ist kaum dokumentiert, umständlich, macht vieles automatisch, ist kaum getestet und kennt kein I²C-INIT. Deshalb verwendet das Open-Maxi-Betriebssystem die erprobten in Software emulierten Routinen der bisherigen OM-Controller. Sie belegen kaum (ca. 40 Byte) mehr OS-Speicher als die IIC-Routinen. Der I²C-Bustakt ist konfigurierbar. In eigenen Programmen kann das IIC-Modul aktiviert und ohne Einschränkungen benutzt werden.
OCBASIC unterstützt bei der Open-Maxi die EXT-Adressierungsart bei LDHX, STHX und CMPHX. Außerdem gibt es den neuen Assemblerbefehl BGND. Andere neue Befehle der HCS08-CPU werden nicht unterstützt.
Daß Assemblerprogramme für die C-Control I Version 1.1 auf der Open-Maxi ohne Neuübersetzung laufen, ist sehr unrealistisch. Denn: Das Speicherlayout der Ports ist anders, der Rechenstack ist anders und an anderer Adresse, der SYSCODE-Bereich beginnt an Adresse $0900 statt $0101 (wird evtl. durch SYS hingebogen), Assembler-Interruptroutinen werden anders vereinbart, der Bustakt ist viel höher (SLOWMODE ON verwenden), USER-RAM liegt an anderer Adresse ($aa statt $a1), Einsprünge ins OS sind notgedrungen nicht an gleicher Adresse und I²C ist anders.
Damit das Betriebssystem nicht zuviel Platz einnimmt, unterstützt die Open-Maxi keinen Hostmode-Befehl zum Auslesen des BASIC- oder SYSCODE-Programms. Es ist aber ein Auslesen über das BDC-Interface am Pin BKGD möglich. Wenn ein Anwender das Auslesen komplett unterbinden möchte, muß er die Security Options des AW60 aktivieren. Siehe Controllermanual zum AW60 von Freescale. Das ist aber noch ungetestet.
Der von DIE HARD entworfene Benchmark zur C-Control Pro befindet sich im Forumsbeitrag 397 und 425.
Beim Einstieg in den Hostmode per "End2Host=ON : END" wird der Empfangsbuffer der Seriellen Schnittstelle nicht geleert.
Die meisten QB8-Controller werden von Freescale offenbar für 3 Volt Betriebsspannung kalibriert, so daß sie bei 5 Volt rund 2,5% zu langsam arbeiten. Dadurch kann es bei CCPLUS und bei der CCBASIC-Windows-IDE während des Programmdownloads zu Übertragungsfehlern kommen. Um die Taktrate dauerhaft zu kalibrieren kann das Utility OSCTRIM verwendet werden. Die bei CCTools verkauften Controller wurden bereits getrimmt.
Bei der Open-Macro ist der Pin PTA2/IRQ sehr empfindlich gegenüber elektromagnetischen Störungen (EMV). In gestörter Umgebung genügt bereits ein Berühren des Ports, um einen Reset auszulösen. In der späteren Applikation sollte deshalb wie im Bild gezeigt eine Z-Diode 5V1 vom Pin nach Masse geschaltet werden. Alternativ läßt sich Störspannung auch mittels herkömmlicher Diode 1N4148 nach VDD (5 Volt) ableiten. Letztere Variante ist aber weniger effektiv. Natürlich könnte man den Pin auch direkt auf VDD legen. In diesem Fall läßt sich der Port allerdings nicht mehr in der Applikation verwenden.

### Dateinamenserweiterungen anzeigen

Nicht zuletzt zum Schutz vor Viren und anderen bösartigen Programmen ist es sinnvoll, die sogenannte Dateinamenserweiterung, auch Dateiendung oder Suffix genannt, von grundsätzlich allen Dateitypen im Windows Explorer anzeigen zu lassen. Zum Beispiel haben ausführbare Programme die Endung "EXE", während ASCII-Textdateien meist die Endung "TXT" besitzen. Unter jeder Windowsversion läßt sich die Anzeige dieser zusätzlichen Information auf etwas unterschiedliche Art und Weise aktivieren. In den folgenden zwei Bildern wird gezeigt, wie es unter Windows 2000 funktioniert.

### DOS-Programme unter Windows

Zur Herstellung der OM-Controller und zur Programmentwicklung werden überwiegend sogenannte DOS-Programme eingesetzt. Neuere Windowsversionen arbeiten bei der Ausführung von DOS-Programmen etwas anders als beispielsweise Windows 95 oder 98. Nachdem ein DOS-Programm zum Beispiel im Windows Explorer per Doppelklick gestartet wurde, wird wie bisher ein DOS-Fenster geöffnet, in dem die Ausgaben des Programms erscheinen. Falls das Programm nur einen kurzen Hinweistext über dessen Benutzung ausgibt wird das Fenster nun aber sehr schnell wieder geschlossen und die Ausgaben gehen verloren. Das läßt sich konfigurieren: Im Windows Explorer muß das DOS-Programm ausgewählt und anschließend die rechte Maustaste gedrückt werden. Es erscheint das sogenannte Kontextmenü, dessen letzter Eintrag "Eigenschaften" lautet. In diesen Eigenschaften kann "Nach Beenden schließen", wie im folgenden Bild gezeigt, deaktiviert werden.

## Unterstützter Befehlsumfang

In der folgenden Tabelle ist aufgeführt, welche Befehle (genauer Tokenbefehle) von der C-Control-Micro und den verschiedenen OM-Mikrocontroller-Varianten unterstützt werden. Ein Sternchen steht dafür, daß der entsprechende Befehl unterstützt wird, ein Bindestrich steht für das Gegenteil.
Bisher bekannte Fehler und Einschränkungen sind unterhalb der Tabelle aufgelistet. Die Liste der Einschränkungen bei der C-Control-Micro ist allerdings nicht vollständig. Beispielsweise sorgt ein verändertes Stackhandling dafür, daß mBasic, CCPLUS und einige OCBASIC- und CCBASIC-Programme nicht mehr mit der C-Control-Micro zusammenarbeiten. Bei fehlerhafter Verwendung von GOSUB und RETURN und bei Berechnungen kann unbemerkt der Stack überlaufen, woraufhin wichtige System- oder Anwenderdaten überschrieben werden. Außerdem wurde im Betriebssystem sehr viel Platz verschenkt, weshalb der den Anwendungen zur Verfügung stehende Programmspeicher deutlich kleiner als bei den OM-Controllern ausfällt. Schließlich läßt sich die Version 2.00 der C-Control-Micro kaum per S19-Systemerweiterung erweitern, weil die meisten Systemerweiterungen nur auf der Version 2.01 arbeiten. Weitere Nachteile gegenüber den OM-Controllern können an anderer Stelle in den Dokus nachgelesen werden.
Einige Funktionen in den OM-Controllern haben Bonuscharakter und sind deshalb nur von eingeschränktem Nutzen. Da sich auf den OM-Controllern allerdings jede Funktion mittels nachladbarem Softwaremodul ersetzen oder nachrüsten läßt, können auch diese Bonusfunktionen bei Bedarf ersetzt werden. Auf diese Weise kann auf der Open-Micro und Open-Mini sogar vollwertiges WORD-Handling realisiert werden, obwohl diese Controller von Haus aus nur BYTE-Arithmetik zur Verfügung stellen. Die Tabelle gibt also den Sachverhalt ohne Erweiterungen wieder.

Token | Zugehöriger Befehl | C-Control-Micro 2.00 | C-Control-Micro 2.01 | Open-Micro | Open-Mini | Open-Midi | Open-Macro | Open-Maxi
0 | NOP | - | - | * | * | * | * | *
1 | PUSH 0 | - | - | * | * | * | * | *
2 | PAUSE | * | *1 | * | * | * | * | *
3 | GOTO | * | * | * | * | * | * | *
4 | IF .. THEN | *2 | *2 | * | * | * | * | *
5 | GOSUB | * | * | * | * | * | * | *
6 | RETURN | * | * | * | * | * | * | *
7 | RETURN INTERRUPT | - | - | * | * | * | * | *
8 | SYS | *3 | *3 | * | * | * | * | *
9 | SLOWMODE | - | * | * | * | * | * | *
10 | PUSH BITPORT | * | * | * | * | * | * | *
11 | PUSH BYTEPORT | - | - | * | * | * | * | *
12 | PUSH WORDPORT | - | - | *13 | *13 | *13 | * | *
13 | POP BITPORT | *4 | *4 | * | * | * | * | *
14 | POP BYTEPORT | - | - | * | * | * | * | *
15 | POP WORDPORT | - | - | *13 | *13 | *13 | * | *
16 | PUSH ADPORT | * | * | * | * | * | * | *
17 | POP DAPORT | - | *5 | - | - | - | - | *
18 | INLASM | - | - | * | * | * | * | *
19 | PUSH -1 | - | - | * | * | * | * | *
20 | PUSH WORDVALUE | * | * | * | * | * | * | *
21 | PUSH BITVAR | * | * | * | * | * | * | *
22 | PUSH BYTEVAR | * | * | * | * | * | * | *
23 | PUSH WORDVAR | - | - | - | - | - | * | *
24 | POP BITVAR | * | * | * | * | * | * | *
25 | POP BYTEVAR | * | * | * | * | * | * | *
26 | POP WORDVAR | - | - | - | - | - | * | *
27 | LOOKTAB | *6 | *6 | * | * | * | * | *
28 | PUSH INTERNALVAR | *7 | *7 | * | * | * | * | *
29 | POP INTERNALVAR | *7 | *7 | * | * | * | * | *
30 | PRINT NUMBER | *8 | *8 | * | * | * | * | *
31 | PRINT STRING | * | * | * | * | * | * | *
32 | PUT | * | * | * | * | * | * | *
33 | RXD | - | - | *14 | *14 | *14 | * | *
34 | GET | * | * | * | * | * | * | *
35 | INPUT | - | - | * | * | * | * | *
36 | ARRAY/POINTER | - | - | * | * | * | * | *
37 | CTS | - | - | *14 | *14 | *14 | *14 | *
38 | PRINTCRLF | - | - | * | * | * | * | *
39 | PUSH 1 | - | - | * | * | * | * | *
40 | NOT | * | * | * | * | * | * | *
41 | AND | * | * | * | * | * | * | *
42 | NAND | - | - | * | * | * | * | *
43 | OR | * | * | * | * | * | * | *
44 | NOR | - | - | * | * | * | * | *
45 | XOR | * | * | * | * | * | * | *
46 | SHL | *9 | *9 | * | * | * | * | *
47 | SHR | *9 | *9 | * | * | * | * | *
48 | RANDOMIZE | - | - | * | * | * | * | *
49 | RAND | *10 | *10 | * | * | * | * | *
50 | NEGIEREN (-) | * | * | * | * | * | * | *
51 | ADDITION (+) | * | * | * | * | * | * | *
52 | SUBTRAKTION (-) | * | * | * | * | * | * | *
53 | MULTIPLIKATION (*) | * | * | * | * | * | * | *
54 | DIVISION (/) | * | * | * | * | * | * | *
55 | MOD | * | * | * | * | * | * | *
56 | ABS | - | - | * | * | * | * | *
57 | SQR | - | - | * | * | * | * | *
58 | MAX | - | - | * | * | * | * | *
59 | MIN | - | - | * | * | * | * | *
60 | GROESSER (>) | * | * | * | * | * | * | *
61 | GROESSER/GLEICH (>=) | * | * | * | * | * | * | *
62 | KLEINER (<) | * | * | * | * | * | * | *
63 | KLEINER/GLEICH (<=) | * | * | * | * | * | * | *
64 | GLEICH (=) | * | * | * | * | * | * | *
65 | UNGLEICH (<>) | * | * | * | * | * | * | *
66 | SGN | - | - | *15 | *15 | *15 | * | *
67 | REMOVETOS | - | - | * | * | * | * | *
68 | ADD BYTEVAR,STACK | - | - | * | * | * | * | *
69 | ADD WORDVAR,STACK | - | - | - | - | - | * | *
70 | Filehandling (OPEN#, etc.) | - | - | * | * | * | * | *
71 | EOF | - | - | * | * | * | * | *
72 | BAUD | *11 | *11 | *16 | *16 | *16 | * | *
73 | INTERRUPT | - | - | * | * | * | * | *
74 | FOR_NEXT_CMP BYTEVAR | *12 | * | * | * | * | * | *
75 | FOR_NEXT_CMP WORDVAR | - | - | - | - | - | * | *
76 | FOR_NEXT_ADD BYTEVAR | * | * | * | * | * | * | *
77 | FOR_NEXT_ADD WORDVAR | - | - | - | - | - | * | *
78 | DBNZ | - | - | * | * | * | * | *
79 | PEEK & POKE | - | - | - | - | - | - | *
80 | TOG | * | * | * | * | * | * | *
81 | PULSE | - | - | * | * | * | * | *
82 | DEACT BITPORT | * | * | * | * | * | * | *
83 | DEACT BYTEPORT | - | - | * | * | * | * | *
84 | DEACT WORDPORT | - | - | *13 | *13 | *13 | * | *
85 | PUSH BYTEVALUE | - | - | * | * | * | * | *
86 | PUSH BYTEVAR,BYTEVALUE | - | - | - | - | * | * | *
87 | PUSH WORDVAR,WORDVALUE | - | - | - | - | - | * | *
88 | LOOKTABBYTE | - | - | - | - | - | * | *
89 | I²C-LCD | - | - | - | - | - | - | *
255 | END | * | * | * | * | * | * | *

1 | Auf der C-Control-Micro funktioniert die Systemerweiterung zum Empfang von RC5-Signalen nicht richtig, wenn ein PAUSE-Befehl verwendet wird.
2 | Die Funktion wurde fehlerhaft implementiert. Die C-Control-Micro führt IF STACK=255 THEN statt IF STACK<>0 THEN aus.
3 | Nur Sprünge in den Bereich $FCxx und $FDxx werden unterstützt. Außerdem werden nur Assemblermodule mit dem korrekten Sicherungscode ausgeführt.
4 | Nach Deaktivierungphasen (z.B. bei der Erstinitialisierung) können Störungen (Glitches) am Port auftreten.
5 | Die PWM-Frequenz beträgt nur 50 Hz. Außerdem können Störungen beim Ändern des PWM-Werts auftreten.
6 | Tabellen müssen WORD-Werte enthalten, obwohl der Controller nur BYTE-Werte verarbeiten kann.
7 | Nicht auf alle internen Variablen kann lesend oder schreibend zugegriffen werden.
8 | Die Ausgabe erfolgt bei Zahlen kleiner 10 mit einer führenden Null.
9 | Die Funktion wurde fehlerhaft implementiert. Die C-Control-Micro führt SHL 0 und SHR 0 als SHL 256 und SHR 256 aus.
10 | Sehr einfaches Verfahren. Liefert keine guten Zufallszahlen.
11 | Die Baudrate von 19200 Baud wurde fehlerhaft implementiert. Der interne Oszillator der C-Control-Micro muß per FREQ2 nachgetrimmt werden.
12 | Die Funktion wurde fehlerhaft implementiert. Die C-Control-Micro führt bei FOR..NEXT einen Schleifendurchlauf zu wenig aus.
13 | Bonusfunktion: Läßt sich zum schnellen und speicherplatzschonenden Zugriff auf BYTEPORT[1] nutzen.
14 | Bonusfunktion: Liefert immer ON zurück.
15 | Bonusfunktion: Liefert höchstwertiges Bit (MSB) zurück.
16 | Bonusfunktion: Parameter wird ignoriert. Ohne nachladbares Softwaremodul werden nur 9600 Baud unterstützt.

## Seiten im Internet

Diese Seiten enthalten wertvolle Hinweise, Demos und Tools rund um die C-Control und die OM. Für den Fall, daß man nicht weiter weiß, kann man versuchen, hier eine Lösung für das Problem zu finden.
Die offizielle Informationssite zur OM
http://om.dharlos.de
Das Forum zur C-Control-1 und zur OM
http://ccintern.dharlos.de/forum
CCTools - Bezug der OM-Controller
http://www.cctools.eu
C-Control-intern - Informationen rund um das Betriebssystem der CC1.1
http://ccintern.dharlos.de
Besonders wichtig sind die offiziellen Websides zu den Controllern 68HC908QT4, QY4, QB8 und MC9S08AW60. Dort können Manuals, Beispielcode und Application Notes zum Controller und zur CPU heruntergeladen werden. Im Anhang des Manuals zum Controller befinden sich auch die umfangreichen Technischen Daten.
Offizielle Webside der Mikrocontroller MC68HC908QT4 (Open-Micro), MC68HC908QY4 (Open-Mini) und MC908QB8 (Open-Midi und Open-Macro)
https://www.nxp.com/products/HC08Q
Offizielle Webside des Mikrocontrollers MC9S08AW60 (Open-Maxi)
https://www.nxp.com/products/S08AW
Der AS05-Assembler von Frank A. Vorstenbosch ist der Defacto-Standard auf der C-Control 1.1, kann aber auch auf 68HC908-Mikrocontrollern wie der Open-Micro, Open-Mini, Open-Midi und Open-Macro eingesetzt werden, da die 6808-CPU objektcode- und quellcodekompatibel zur 6805er ist. Die HCS08-CPU des AW60s ist abwärtskompatibel zur 6808. Die Betriebssysteme wurden vollständig mit dem sehr zuverlässigen AS05-Assembler und Macros für die neuen 6808-Befehle erstellt.
Frank's Cross Assemblers
http://www.kingswood-consulting.co.uk/assemblers