IC35 SDK Anmerkungen

Für die Richtigkeit der Angaben kann natürlich keine Gewähr übernommen werden!

Da wir so einige Fragen zum IC35-SDK erhalten haben, an dieser Stelle Anmerkungen zur IC35 Software-Entwicklung anhand eines Beispiel-Projekts Irtrans, Übertragung von Daten über die Infrarot-Schnittstelle des IC35 im RAW Protokoll (ohne IRDA).
Ich habe eine Anwendung, bei der ich ab und zu Meldungen (ASCII-Strings) auf eine Laufschrift-Anzeige übertragen muss. Es handelt sich um eine unidirektionale Schnittstelle, Übertragungsrate 9600 Baud. Da es die bekannten Probleme mit der Beschaffung eines V24 Kabels gibt, habe ich einen Infrarot-Umsetzer gebaut. Es werden einfach die IRDA-konformen Infrarot-Pulse (zwischen 1.41 µsec und 3/16 der Bitlänge, entspricht ca. 19.5 µsec bei 9600 Baud) entsprechend der gewünschten Baudrate verlängert (104 µsec bei 9600 Baud) . Das ist zwar keine gesicherte Verbindung, aber da es nur wenige Daten sind, die zudem anschließend optisch überprüft werden können, soll das kein Problem darstellen.
Benötigte Bauteile: IRDA-Tranceiver, Oszillator, Zähler, NAND-Gatter, RS232 Wandler.
Schaltplan siehe unten.
Der Sourcecode für das Projekt Irtrans kann hier heruntergeladen werden.

Aber jetzt zuerst zur Software Beschreibung.

Am einfachsten erstellt man ein IC35-Projekt, wenn man sich eine Kopie des Beispiels VDemo aus dem IC35-SDK macht, das Directory umtauft in diesem Fall in Irtrans, im Directory Irtrans dann die Dateien VDemo.dsp und VDemo.rc in Irtrans.dsp und Irtrans.rc umbenennt. Anschließend ersetzt man mit einem Text-Editor in der Datei Irtrans.dsp alle Verweise auf VDemo durch Irtrans (VDemo kommt 12 mal vor). Als nächstes öffnet man mit Visual-C das Project Irtrans.dsp und schließt es gleich wieder. Beim Speichern wird dann der Workspace Irtrans.dsw erzeugt. Man hat nun auch bereits die zwei Dateien main.c und data.c vor sich, in data.c kommen alle globalen Variablen, alle müssen mit 0 statisch vorinitialisiert werden, z.B. S16 awDummy[10] = { 0};  , da Speicherplatz für Variable nur dann angelegt wird ! Falls man keine globalen Variablen benötigt, kann man diese Datei entfernen. Ansonsten muss mindestens eine (Dummy-) Variable darin vorkommen, sonst beschwert sich der Compiler. Da man nur 2 KB Stack zur Verfügung hat, sollte man alle größeren Datenfelder zu den globalen Variablen legen.
 

Zu den Bänken:

Ein Z80 kann nur 64 KB adressieren, um solche Einschränkungen zu umgehen, hat man Bankswitching-Verfahren entwickelt.
Offensichtlich wurde beim IC35 ein vom Compiler unterstütztes Bankswitching in 16 K Bänken eingesetzt, d.h. Programm- und Daten-Bereich sind in (unabhängige) 16 K Bänke aufgeteilt, wobei der Code-Bereich (ROM) in den ersten beiden Bänken (0x0000 - 0x3fff und 0x4000 - 0x7fff) liegt, der Daten-Bereich (RAM) über die anderen beiden Bänke (0x8000 - 0xbfff und 0xc000 - 0xffff) adressiert wird.
Vermutlich läuft das ROM Bankswitching nur über den Bereich 0x4000 - 0x7fff, die IC35-SDK Bibliotheks-Funktionen werden fest über den Bereich 0x0000 - 0x3fff angesprochen.
Analog verhält es sich mit dem RAM-Bereich (für globale Daten), dieser wird über den Bereich 0x8000 - 0xbfff abgebildet, Stack etc. liegt immer im Bereich 0xc000 - 0xffff.

Zuweisung der Bänke über den Projekt Maker:

Wenn man Programme selber entwickelt, muss man die Sourcen (*.c) (bzw. eigentlich die zugehörigen Objekte) in eine ROM-Bank legen. Dazu erzeugt man sich eine neue Bank (NEW BANK) und schiebt main.c in die so erzeugte App. Bank 0, ebenso evtl. zusätzliche Source Files. Erst wenn das Programm größer 16 KB wird, muss man eine zweite Bank anlegen, ansonsten kann man die folgenden Zeilen ignorieren und bei der Bank für globale Variable weiter lesen.
Entgegen der SDK-Dokumentation bekommt die erste Bank die Nummer 0 usw. . Die Zuordnung, welche Funktionen über Bankswitching gerufen werden, macht ein extra Lauf beim Kompilieren (downcall). Dieses downcall erkennt allerdings nur Funktionen, bei deren Definition die öffnende spitze Klammer in der nächsten Zeile steht !!!, also z.B.

void srand(U16 sStart)
{

Anhand der während des Kompilieren/Linkens erzeugten Datei func.map kann man überprüfen, ob alle "externen" Funktionen als solche erkannt wurden. Sie sollte dann in diesem Beispiel so aussehen:

srand*0X0001
 

wobei die Hex-Nummer die Bank bedeutet.

Übrigens, in main.c wird der Aufruf
    srand(0xaffe);
ersetzt durch
    downcall(0X0048,srand,0xaffe);

Als nächstes benötigt man evtl. eine Bank für globale Variable (Default RAM Bank). Dazu klickt man die Default RAM Bank an und schiebt data.c hinein.
Alle globalen Daten müssen in dieser Bank liegen und mit 0 vorinitialisiert sein, sonst beschwert sich der Compiler. Statische Daten erlaubt der Compiler nicht.
Das Bankswitching ist vermutlich auch die Ursache für die Compiler Probleme bei String-Funktionen (die im SDK üblichen Remarks: "xxx should be a pointer to a character string array, not a constant").Diese Funktionen haben offensichtlich Probleme bei der Verwaltung der aktuellen Code-Bank (0x4000 - 0x7fff).
Problematisch wird es, wenn man (nicht zu 0) vorinitialisierte Daten benötigt. So besteht z.B. die Spielstrategie für Mastermind aus > 4 KByte (auf PC errechneter) Daten. Um sie in die Applikation zu bekommen haben wir sie sozusagen in ein Bitmap gewandelt. Bitmaps beim IC35-SDK bestehen aus X- und Y- Größe (in Pixel), gefolgt von X * Y / 8 Byte binärer Daten. Diese Daten haben wir in ein File try.img geschrieben. Anschließend wurde in Visual-C eine neue Resource IMAGE erzeugt, die das File try.img referenziert. Dieses File kann man dann im Z80 Project Maker in die Resource Bank legen. Visual-C erzeugt die Definitionen TRY_BANK und TRY_OFFSET in der Datei res.h. In der Applikation können dann über

Daten aus der Resource Bank eingelesen werden.
Das Ganze hat den Nachteil, dass man mindestens 2 Bänke benötigt (32 KB) und somit der knappe Applikationsspeicher strapaziert wird.
Eine andere Möglichkeit ist, nach dem Fertigstellen der Applikation die Daten an das Ende des Programms zu patchen. Eine IC35 Applikation hat eine minimale Länge von 16 KB, wobei die nicht benötigten Speicherzellen am Ende des Programms mit 0 aufgefüllt sind. Diese kann man dann durch initialisierte Daten ersetzen. Dazu macht man sich ein Windows-Programm das die Datei <xxx.app> binär einliest, die letzen Bytes auf 0 überprüft, sie durch die initialisierten Daten ersetzt und anschließend eine neue Datei erzeugt. Angenommen man benötigt 351 Bytes initialisierte Daten:

#define    IDATA_LENGTH    351

in data.c:


und in main.c:


Projekt Irtrans


Folgende Voraussetzungen:

Quellen unter c:\Source\Ic35\Sw\'<'Project Name'>' (hier Irtrans)
Header Files unter c:\Source\Ic35\Include (Kopieren von \Ic35sdk\Include)
Libraries unter c:\Source\Ic35\Lib (Kopieren von \Ic35sdk\Lib)

1. Customize von Visual-C wie im SDK angegeben:

1.1 Configure IC35 Project (IC35 Project Maker)

Command: C:\Ic35sdk\CCTools\Tool\Dsp2Mak.exe
Arguments: $(WkspDir)\$(WkspName)
Initial Directory: $(WkspDir)

Dieses Kommando wird benötigt, um ein Makefile zu erzeugen.

1.2 Make IC35 Project

Command: C:\Programme\Microsoft Visual Studio\VC98\Bin\Nmake.exe (o.ä.)
Arguments: /nologo $(WkspName)_z80.mak
Initial Directory: $(WkspDir)

Dieses Kommando übersetzt und linked das Projekt.

1.3 Name IC35 Project ( neuer Punkt )

Command: addhead.exe
Arguments: app.rom $(WkspName).app ic35.nam
Initial Directory: $(WkspDir)\Z80_Out

Mit diesem Kommando setzt man den Applikationsnamen in den Header und erzeugt eine Datei mit der .app Extension für den Download über die Sync-Station. Es ersetzt den im SDK angegebenen Download über das nicht lieferbare RS232-Kabel.

2. Erstellen von Projekten

Am einfachsten ist es, wenn man sich eine Kopie von VDemo macht.

2.1 Kopieren

\Ic35sdk\Example\VDemo -> \Source\Ic35\SW\Irtrans

2.2 Umbenennen

Unter \Source\Ic35\SW\Irtrans:
VDemo.dsp -> Irtrans.dsp
VDemo.rc -> Irtrans.rc

2.3 Ersetzen

in Datei Irtrans.dsp: alle Einträge VDemo durch Irtrans ersetzen (12)

2.4 Visual-C

Unter Visual-C Irtrans.dsp (als Project) öffnen, erzeugt dann beim Speichern einen Workspace (Irtrans.dsw)

3. Erzeugen der Applikation

Nachdem man die Applikation mit dem Emulator ausgetestet hat, erzeugt man den Target-Code für den IC35.

3.1 IC35 Project Maker

TOOLS -> Configure IC35 Project
Klicken auf NEW BANK erzeugt ein App. Bank 0
App. Bank 0 anklicken und in diese Bank dann main.c verschieben.
Default RAM Bank anklicken und data.c hineinschieben.
Falls bei einem erneutem Aufruf von TOOLS -> Configure IC35 Project die Dateien nicht mehr in den Bänken stehen, ist das ein Zeichen dafür, dass bei den General Einstellungen die Pfade nicht stimmen.

3.2 Target Code übersetzen/linken

TOOLS -> Make IC35 Project
Unter Win95/98/ME® wartet der Compiler 2 mal auf Tastatur Eingabe (beliebige Taste), zum Schluss muss man auch noch mit CTRL-C abbrechen, unter NT® läuft der Compiler normal durch. Der Compiler erzeugt ziemlich viele Warnungen, die aber ignoriert werden können.
Erzeugt wird die Datei App.rom im Subdirectory Z80_Out.

3.3 Namen in Header einfügen

Als nächstes muss im Header der Applikation der Applikationsname eingetragen werden.
TOOLS -> Name IC35 Project
erzeugt in Subdirectory Z80_Out die Datei Irtrans.app aus der Datei App.rom. Dazu muss mit einem Texteditor vorher noch eine Datei Ic35.nam erzeugt werden, die den gewünschten Namen der Applikation enthält, in diesem Fall Irtrans.
Die Datei Irtrans.app kann nun mit dem IC35 Manager heruntergeladen werden.

4.Schaltplan Irtrans Modul


Michael Fitzek

Änderungsstand: 11.11.2001

© www.Moritz-Fitzek.de