;----------------------------------------------------------------- ; Angepasst für ELZET80 CPU/IEC Baugruppe ; Franz Lange ; 17.11.2020 ;----------------------------------------------------------------- ; 25.11.2020, 21:30h - Testroutinen ohne Stack ; 29.11.2020, 22:55h - Memory Adress Test FC00-FFFF ; 30.11.2020, 10:50h - Neue Kommandos, Input, Output, Clear Memory ; 01.12.2020, 13:35h - SIO-Programming, Memory-Test ; 02.12.2020, 10:20h - HEX -> ASCII ; 03.12.2020; 21:10h - Debug Minimon ; 04.12.2020; 21:50h - Basis-Adresse ist F000H, nicht E000 wie im Schaltplan ; 07.12.2020; 17:35h - Check ELZET80 FDC ; 08.12.2020; 17:35h - Check Memory on ELZET80 FDC ; 09.12.2020; 11:00h - Erweiterung Minimon-Kommandos ; 10.12.2020; 23:25h - Memory-Test-Kommando ; 11.12.2020; 10:20h - LOW Memory + EPROM ;----------------------------------------------------------------- ; Link : https://archive.org/stream/ct8312/ct8312_djvu.txt ; ; c’t 1983, Heft 12 ; ; MINIMON ; ; Kurzes Monitorprogramm für Z80-Rechner ; ; Andreas Burgwitz ; Dieses kleine Maschinenprogramm bietet die wichtigsten Funktionen, ; die ein Monitorprogramm haben sollte. MINI- MON belegt nur 605 Bytes, ; umfaßt aber fünf wesentliche Befehle. Da das Programm nur die Betriebssystemroutinen ; Tastaturabfrage und Bildschirmausgabe verwendet, dürfte es sich leicht für verschiedene ; Z80-Rechner anpassen lassen. ; ; Bei der Programmierung in Maschinensprache benötigt man ein Hilfsprogramm, das es er- ; laubt, Daten in einzelne Speicherzellen zu schreiben und wieder herauszulesen. MINI- ; MON bietet diese Möglichkeiten. Als Befehle stehen zur Verfügung: ; ; MODIFY (M) ; ; Sichten und Ändern des Inhalts einer Speicherzelle ; ; ## TABULATE (T) ## umbenannt in DISPLAY (D) ; ; Auflistung der Hex-Werte eines Speicherbereichs ; ; JUMP (J) ; ; Sprung zu angegebener Adresse ; ; ASCII (A) ; ; Auflistung der ASCII- Werte eines Speicherbereichs ; ; BREAKPOINT (B) ; ; Setzen und Löschen eines Haltepunktes ; Das Monitorprogramm, im folgenden kurz Monitor genannt, benutzt zwei Routinen des ; Rechnerbetriebssystems. Diese Routinen dienen zur Ausgabe eines Zeichens auf den Bild- ; schirm sowie zur Abfrage der Tastatur. Da aber beide Programme grundsätzlich in jedem ; Rechner vorhanden sind, dürfte die Anpassung des Programms an den verwendeten ; Computer keine Probleme bereiten. Nähere Hinweise zur Anpassung und Modifikation ; des Programms stehen unter dem Abschnitt ‘Modifikationen’. Das Programm ist modu- ; lar aufgebaut. Diese Struktur erlaubt eine Erweiterung, um beliebige Befehle sowie die Ver- ; wendung von Unterprogrammen des Monitors durch andere Programme. ; ; Neue Kommandos: ; ; INPUT (I) ; I (I/O-Adresse) ; ; OUTPUT (O) ; O (I/O-Adresse) (Datum) ; ; MEMORY PAGE (P) ; P (PAGE) {0 - F} ; ; CLEAR MEMORY (C) ; C (Anfangsadresse) (Endadresse) ; ; TESTE MEMORY (T) ; T (Anfangsadresse) (Endadresse) ; ; Die Struktur des Programms ; ; Der Monitor besteht im wesentlichen aus zwei großen Blöcken. Der eine Block ent- ; hält mehrere Module, die zum Teil von anderen Programmen als Unterprogramme verwendet ; werden können. Der andere Block enthält die Befehlsroutinen. Diese enden alle mit "RETURN", ; so daß sie ebenfalls von anderen Programmen auf gerufen werden können. ; ; Nach dem Start des Monitors erfolgt die Initialisierung. Dabei wird zuerst der Stack defi- ; niert. Danach löscht die CPU einen Speicherbereich, der als Buffer für die Tastatureingabe ; dient. Der Computer meldet sich dann mit dem Zeichen ‘ # ’ und fragt anschließend die Ta- ; statur mittels des Unterprogramms KBIN ab. Dieses Programm wartet solange auf Zei- ; chen von der Tastatur, bis der Benutzer ein Carriage Return eingibt. Alle zuvor eingegebe- ; nen Zeichen stehen in dem BUFF genannten Speicherbereich. Wird diese Routine von ; einem anderen Programm aufgerufen, kann als Einsprung KBIN 1 gewählt werden, da ; dann der Anfang des Buffers durch den Inhalt des Registers HL bestimmt ist. Nach der Ein- ; gabe eines Befehls durchsucht das Programmodul EXEC eine Befehlstabelle, wobei nur das ; erste eingegebene Zeichen mit denen in der Tabelle verglichen wird. Die Tabelle enthält den ; Befehlsbuchstaben, gefolgt von der Einsprungsadresse der Befehlsroutine. Ergibt der Ver- ; gleich des eingegebenen Zeichens mit denen in der Tabelle keine Gleichheit, findet EXEC ; das Endzeichen der Tabelle (FF Hex). Das bewirkt, daß die CPU zu der Eingabeschleife zu- ; rückspringt. Ist das eingegebene Zeichen identisch mit einem der Tabelle, legt das Programm ; JEXE die Rücksprungadresse des Monitors auf den Stack und verzweigt zu der Befehls- ; routine. Die weiteren Programmodule dienen der ASCII-HEX-Wandlung (AHEX) und ; dem Gewinnen der Befehlsargumente (GETA). Das Programm PRHEX druckt den Akkuinhalt in hexadezimaler ; Form — eine Funktion, die man in verschiedenen Programmen häufig braucht. ; ; DAS ARBEITEN MIT DEM MONITOR ; ; Der Befehl MODIFY dient dem Sichten und Verändern des In- ; halts einer Speicherzelle. Die Eingabe des Befehls erfolgt in der Form: ; ; M (Adresse) ; ; Angezeigt werden die Speicheradressen sowie der Inhalt dieser Zelle. Der Cursor steht hinter ; dem Datum. Man kann jetzt entweder ein neues Byte eingeben, was sofort in der angezeig- ; ten Speicherzelle abgelegt wird, oder durch Drücken der CR- Taste zur nächsten Speicherzel- ; le weitergehen, wobei der Speicherinhalt nicht verändert wird. Zu dem Monitor kann ; man durch Eingabe eines ',' und Drücken der CR-Taste zurückkehren. ; ; Der Befehl ## TABULATE ## DISPLAY bewirkt die Anzeige eines Speicherbereichs in hexadezimaler ; Form (Hexdump). Die Form dieses Befehls ist: ; ; ( T Startadresse Endadresse) - alt ; ; D (Startadresse) (Endadresse) - neu ; ; ; Angezeigt wird am Anfang jeder Zeile die jeweilige Speicheradresse, danach folgen (acht) sechzehn ; Datenbytes. Die Anzeige kann jederzeit durch Drücken der Leertaste angehalten und wie- ; der fortgesetzt werden. Ist die Anzeige nicht gestoppt, kann man auch hier vor Erreichen ; der eingegebenen Endadresse durch die Eingabe von ',' zum Monitor zurückkehren. ; ; Das gleiche Format wie (TABULATE) DISPLAY verwendet der Befehl ASCII, wobei anstelle der ; hexadezimalen Darstellung der Speicherinhalt in ASCII-Zeichen angezeigt wird. Zeichen ; die nicht gedruckt werden können, werden durch ein Leerzeichen ersetzt. ; ; Der Befehl JUMP setzt den Programmcounter auf die angegebene Adresse, was den ; Sprung zu einem dort beginnenden Programm bedeutet. ; Die Form des Befehls ist: ; J (Startadresse des Programms) ; Der Monitor bietet die Möglichkeit einen Software - BREAKPOINT zu setzen. ; Die Form ist dabei: ; ; B (Breakadresse) ; ; Die Adresse, auf die der Breakpoint gesetzt werden soll, muß immer das erste Byte eines ; Maschinenbefehls sein. Dieser Befehl wird durch eine drei Byte lange Sequenz ‘Call BREAK’ ; ersetzt. Der ursprünglich an dieser Stelle stehende Befehl wird in einem Buffer des Moni- ; tors gesichert. ; Durch die Eingabe von: ; B Taste CR drücken werden die drei Byte ‘Call BREAK’ wieder gegen die alten ; Daten ausgetauscht. Wird beim Lauf des Programms die Break-Sequenz erreicht, über- ; nimmt der Monitor die Werte der Z80-Register und zeigt sie in der Form ; Register Wert 1 (Wert 2) an. Wert 1 steht für den Inhalt des Registers (Anzeige Hexade- ; zimal). Wert 2 zeigt den Inhalt der Speicherzelle an, die durch das Register adressiert sein ; könnte. Auch diese Daten werden in hexadezimaler Form dargestellt. Nach der Anzeige ; aller Register wartet der Monitor auf die Eingabe weiterer Befehle. ; ; Das Monitorprogramm akzeptiert die Befehlseingabe auch dann, wenn zwischen dem Be- ; fehlsbuchstaben und dem ersten Argument kein Leerzeichen steht. Zwischen zwei Ar- ; gumenten ist das Leerzeichen jedoch unabdingbar. ; ; Modifikationen ; ; Der Monitor wurde für einen TRS-80 geschrieben, verwendet aber keine schwierig adaptier- ; baren Routinen des Betriebssystems. ; Soll das Programm auf anderen Computertypen laufen, müssen folgende System- ; definitionen beachtet werden: ; ; 1: KBDM, Eine einmalige Abfrage der Tastatur. ; Das Zeichen steht im Akku. ; Wurde keine Taste gedrückt, ist der Akku ‘ 0 ’. ; ; 2: KBD Abfrage der Tastatur, bis ein Zeichen eingegeben wird, ; sonst wie KBDM. Diese Routine muß nicht dem Betriebssystem entnommen werden ; man kann sie unter Verwendung von KBDM selbst schreiben. ; ; 3: CRT Ausgabe des Akkuinhalts auf den Bildschirm ; unter Berücksichtigung der Steuerzeichen. ; ; Das Zeichen CON bewirkt beim TRS-80, daß der Cursor ‘eingeschaltet’, das heißt sicht- ; bar ist. Dieses Zeichen wird nur einmal bei der Initialisierung des Monitors ausgegeben. ; ; Der Speicherbereich, in dem der Monitor liegt, kann unabhängig von dem Bereich des ; Buffers verändert werden. Das Programm läßt sich aber nicht frei im Speicher verschieben. ; ; Das Programmlisting ; ;-------------------------------------------------- ; MINI-MONITOR FUER Z80 ; VON ; A. BURGWITZ ;-------------------------------------------------- ; Angepasst a TASM ;---------------------------------------------------------------------- #define EQU .equ ; for TASM #define DB .byte ; for TASM #define DW .word ; for TASM #define DS .block ; for TASM #define ORG .ORG ; for TASM #define END .end ; for TASM #define PAGE .page ; for TASM #define TITLE .title ; for TASM ;---------------------------------------------------------------------- ; Angepasst an ELZET 80 CPU/IEC und ELZET80 FDC-3 mit 2 x 64K DRAM ; ; Nur mit ELZET 80 CPU/IEC mit integriertem 2K SRAM ; liegt der Monitor im Adressbereich F000 - F7FF ;---------------------------------------------------------------------- #define CPUIEC 1 ; Zielhardware = ELZET80-IEC-CPU #define INTRAM 1 ; IEC-CPU uses internal RAM AT F000H #define FDC_03 1 ; ELZET80-IEC-CPU + FDC3 mit 128 MB RAM ;---------------------------------------------------------------------- ; ; S Y S T E M D E F I N I T I O N E N ; ;---------------------------------------------------------------------- ; NUR TRS-80 ; für ELZET80 nicht relevant ; ; KBDM EQU 002BH ; EINMALIGE TASTATURABFRAGE ; KBD EQU 0049H ; TASTATURABFRAGE BIS EINGABE ; CRT EQU 0033H ; ZEICHEN IN AKKU AUF SCHIRM GEBEN ;---------------------------------------------------------------------- ; ELZET80 CPU/IEC CPU-Baugruppe SIOA_DAT EQU 04H ; SIO/2-A - Data Register SIOB_DAT EQU 05H ; SIO/2-B - Data Register SIOA_CTL EQU 06H ; SIO/2-A - Control Register SIOB_CTL EQU 07H ; SIO/2-B - Control Register ;---------------------------------------------------------------------- ; SIO_CH_RST EQU 18H ; Z80 SIO Channel RESET SIO_WR0 EQU 00H ; Z80 SIO Write Register 0 SIO_WR1 EQU 01H ; Z80 SIO Write Register 1 SIO_WR3 EQU 03H ; Z80 SIO Write Register 3 SIO_WR4 EQU 04H ; Z80 SIO Write Register 4 SIO_WR5 EQU 05H ; Z80 SIO Write Register 5 SIO_RXA EQU 00000001B ; RX Character Available SIO_TXE EQU 00000100B ; SIO Transmit Buffer Empty ; ;---------------------------------------------------------------------- ; ELZET80 CPU/IEC CPU-Baugruppe PIO_PAD EQU 00H ; PIO PORT A DATEN PIO_PBD EQU 01H ; PIO PORT B DATEN PIO_PAC EQU 02H ; PIO PORT A, Control PIO_PBC EQU 03H ; PIO PORT B, Control ; DRAM_ST EQU 1000H ; DRAM Start Adresse (ext.) ;---------------------------------------------------------------------- ; ELZET80 FDC3 Floppy Controller ; ELZET80 FDC3 Floppy Controller - PIO FD3BAS EQU 60H ; FDC3 I/O Basis-Adresse FD3PAD EQU FD3BAS + 0CH ; FDC3 PIO Data A FD3PBD EQU FD3BAS + 0DH ; FDC3 PIO Data B FD3PAC EQU FD3BAS + 0EH ; FDC3 PIO Control A FD3PBC EQU FD3BAS + 0FH ; FDC3 PIO Control B ; F3PIOM3 EQU 11001111B ; PIO MODE 3 F3PAIOC EQU 00100000B ; PORT A I/O Control Word F3PBIOC EQU 10000000B ; PORT B I/O Control Word F3PAINT EQU 00010111B ; PORT A Interrupt Control Word ; DI, OR,LOW, MASK follows F3PBINT EQU 00010111B ; PORT B Interrupt Control Word ; DI, OR,LOW, MASK follows F3PAMSK EQU 11111111B ; PORT A Interrupt MASK Word ; Mask all interrupts F3PBMSK EQU 11111111B ; PORT B Interrupt MASK Word ; Mask all interrupts ; ; F3PA7 = Output, FM/MFM (Density) ; F3PA6 = Output, SIDE-SEL ; F3PA5 = Input, Two Sided, 8" Interface ; F3PA4 = Output, MINI, Umschaltung 8" 5-1/4" ; F3PA3 = Output, Drive Select 3 ; F3PA2 = Output, Drive Select 2 ; F3PA1 = Output, Drive Select 1 ; F3PA0 = Output, Drive Select 0 ; PORT-B-7 = Input, Disk Change ; PORT-B-6 = Motor-ON-3 ; PORT-B-5 = Motor-ON-2 ; PORT-B-4 = Motor-ON-1 ; PORT-B-3 = Output A19 ; PORT-B-2 = Output A18 ; PORT-B-1 = Output A17 ; PORT-B-0 = Output A16 ; ; ELZET80 FDC3 Floppy Controller - DMA ; ; ELZET80 FDC3 Floppy Controller - FDC-1793 F1793CMD EQU FD3BAS + 08H ; FDC-1793 Command Register F1793TRK EQU FD3BAS + 09H ; FDC-1793 Track Register F1793SEC EQU FD3BAS + 0AH ; FDC-1793 Sector Register F1793DAT EQU FD3BAS + 0BH ; FDC-1793 Data Register F1793STA EQU FD3BAS + 08H ; FDC-1793 Status Register ;---------------------------------------------------------------------- ; ; STEUERZEICHEN UND TOP OF STACK ; CON EQU 0EH ; CURSOR ON BEI TRS-80 CR EQU 0DH ; CARRIAGE RETURN LF EQU 0AH ; LINEFEED BS EQU 0BH ; BACKSPACE #ifdef INTRAM ; TOS EQU 0F3FFH ; TOP OF STACK, CPU-IEC internal RAM, Standard TOS EQU 0F7FFH ; TOP OF STACK, CPU-IEC internal RAM, Debug #else TOS EQU 0FFFFH ; TOP OF STACK #endif ; ;-------------------------------------------------- ORG 0000H ; RESET-ENTRY ;-------------------------------------------------- RESET DI ; JR HW_INIT ; INIT I/O ;-------------------------------------------------- ; INIT SIO/2 (A und B) HW_INIT LD A,SIO_CH_RST ; SIO - Channel RESET OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,SIO_WR4 ; Address WR4 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,044H ; 0x44, 0100 0100b - > ; X16 Clock Mode, ; 1 Stop-Bits, Even/Odd-Parity = 0 ; Parity-Enable = 0 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,SIO_WR3 ; WR3 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,0C1H ; 0xC1, 0100 0001b -> ; RX = 8 Bits/Char, Autoenables = 0 ; Bit(4:1) = 0, RX-Enable = 1 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,SIO_WR5 ; WR5 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,068H ; 0x68, 0110 1000b -> ; DTR = 0, TX = 8Bits/Char, Send-Break = 0 ; TX-Enable = 1, RTS = 0, Bit2 und Bit0 = 0 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,SIO_WR1 ; WR1 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,00H ; WR1 = 00 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port LD A,SIO_WR0 ; WR0 OUT (SIOB_CTL),A ; SIO/2-B-Control-Port OUT (SIOA_CTL),A ; SIO/2-A-Control-Port ; INIT Z80-PIO JP TST_HW ; Teste Hardware ; Adresse 42H M0042 DB "MINIMON EI V 0.1" ; Monitormeldung M0052 DB 0DH,0AH ; neue Zeile M0054 DB 00H ; Endezeichen RAM_OK1 DB "OK",0DH,0AH,00H ; RAM_BD1 DB "BAD",0DH,0AH,00H ; M0060 DB 13H,13H,12H,20H,21H ; Version 13, 13.12.20, 21:15 M0065 DB 15H ; ; ORG 0066H ; NMI Entry LD HL,LD_OK ; MINIMON im RAM? LD A,055H ; 55H im RAM ? CP (HL) ; JR NZ,NMSTP ; NEIN, EPROM, Halt on NMI INC HL ; LD A,0AAH ; 0AAH im RAM ? CP (HL) ; JR NZ,NMSTP ; NEIN, EPROM, Halt on NMI LD HL,NMTXT ; MINIMON im RAM > "NMI AT: " CALL PRTXT ; ausgeben POP HL ; PC CALL PRHL ; ausgeben CALL CRLF ; neue Zeile LD HL,0000H ; -> setze auf RESET Enty fort PUSH HL ; LD HL,BREAK ; zunaechst Register-Ausgabe PUSH HL ; wie bei Breakpoint RETN ; Return from NMI NMSTP LD DE,NMTX1 ; MINIMON im EPROM, "NMI" LD HL,NMHLT ; Return Adresse JP TXTO_S0 ; ausgeben (CALL) NMHLT HALT ; HALT JP RESET ; START NEW ;-------------------------------------------------- NMTXT DB 0DH,0AH,"NMI AT: " ; DB 00H ; NMTX1 DB "NMI ",00H ; TEXT when there is no RAM ;-------------------------------------------------- #ifdef INTRAM RAM_ST1 DB 0DH,0AH,"Testing RAM at" ; IEC-CPU, External RAM DB " F000H - F3FFH : ",00H #else RAM_ST1 DB 0DH,0AH,"Testing RAM at" ; IEC-CPU, Internal RAM DB " FC00H - FCFFH : ",00H #endif ; FDC3_FI DB 0DH,0AH,"FIND FDC-3 - ",00H FDC3_NP DB "NOT " FDC3_PR DB "PRESENT",0DH,0AH,00H FDC3_RT DB "TESTING RAM ON FDC-3 - ",00H ; MOV_RAM DB 0DH,0AH DB "MOVE CODE TO RAM ",00H ; TST_HW LD SP,0100H ; Stack vorlaeufig auf 0100H LD C,'#' ; Erstes Zeichen LD HL,RAMT00 ; Return Adresse -> HL JP CHO_S0 ; auf Serial 0 ausgeben RAMT00 LD DE,RAM_ST1 ; Adresse String -> DE LD HL,MRETB ; Return-Adresse -> HL JP TXTO_S0 ; Text ausgeben ; Teste zunächst zwei RAM-Zellen MRETB LD HL,TSTRAM ; Adresse RAM (Buffer-Bereich) LD B,055H ; Testpattern 055H MRETL LD (HL),B ; Testpattern -> RAM NOP ; warte NOP ; warte LD A,(HL) ; Lese Testpattern CP B ; OK ? JR NZ,RT0_FE1 ; NEIN, "<" ausgeben LD A,B ; CPL ; invertiere Testpattern LD B,A ; INC HL ; zweiter TP auf der nächsten Adresse AND 80H ; zweiter Testpattern OK? JR NZ,MRETL ; nein Teste mit invertiertem Pattern LD C,'>' ; OK, ">" ausgeben LD HL,MRETC ; Return-Adresse JP CHO_S0 ; auf Serial 0 ausgeben MRETC LD HL,STAMON ; Anfangsadresse CODE im RAM MRETF LD D,H ; Adresspointer -> DE LD E,L ; LD (HL),D ; High Byte Adresspointer -> RAM INC HL ; LD (HL),E ; Low Byte Adresspointer -> RAM INC HL ; LD A,L ; OR A ; 256 Bytes geschrieben JR NZ,MRETD ; nein NOP ; hier Punkt ausgeben EX DE,HL ; save Memory-Adresse -> DE LD HL,RETPKT ; Return-Adresse -> HL LD C,'.' ; Punkt JP CHO_S0 ; ausgeben RETPKT EX DE,HL ; Memory-Adresse -> HL MRETD LD A,H ; incremented past 1 KByte AND 03H ; begrenze Vergleich auf 1K OR L ; JR NZ,MRETF ; nein -> nächster Adresspattern -> RAM ; LD HL,STAMON ; Ja, überprüfe ab erster Code Adresse MRETE LD D,H ; Adresspointer -> DE LD E,L ; LD A,D ; LD B,D ; Expected Value -> B LD A,(HL) ; High Byte CP D ; correct ? JR NZ,RT1_FE1 ; nein -> Fehler INC HL ; LD A,E ; LD B,E ; Expected Value -> B LD A,(HL) ; LOW Byte CP E ; correct ? JR NZ,RT1_FE1 ; nein -> Fehler INC HL ; LD A,L ; 256 Bytes gelesen ? OR A ; JR NZ,MRETG ; nein NOP ; hier + ausgeben EX DE,HL ; Memory-Adresse -> DE LD HL,RETHAS ; Return-Adresse -> HL LD C,'+' ; Pluszeichen JP CHO_S0 ; ausgeben RETHAS EX DE,HL ; Memory-Adresse -> HL MRETG LD A,H ; incremented past 1K ? AND 03H ; begrenze auf 1K OR L ; JR Z,RT1_OK1 ; ja, FC00 - FFFF is OK JR MRETE ; nein, nächstes Wort ; FC00 - FFFF erfolgreich getestet RT1_OK1 LD DE,RAM_OK1 ; Adresse String -> DE LD HL,RT1_END ; Return-Adresse -> HL JP TXTO_S0 ; Text ausgeben (CALL DIRECT) RT1_END JR RAMT02 ; BASIS-RAM OK, weitere RAM Tests ;-------------------------------------------------- ; ; Fehler erste RAM-Adresse ; IN HL = RAM-Adresse ; B = Write Data ; A = Read Data RT0_FE1 EX DE,HL ; RAM-Adresse -> DE LD IY,RT0_HLT ; Return Adresse -> IY JP RAM_FEH ; Fehleradresse, Write Date RT0_HLT HALT ; und Read Data ausgeben JR RT0_HLT ; und HALT ; ;-------------------------------------------------- ; ; RAM-Fehler ; ; STANDARD RAM FC00 - FFFF ; ; CPU-IEC RAM at F000 - F3FF ; IN HL = RAM-Adresse ; B = Write Data ; A = Read Data RT1_FE1 EX DE,HL ; RAM-Adresse -> DE LD IY,RT1_FE2 ; IY = Return-Adr., Fehleradresse, JP RAM_FEH ; Write Data und Read Data ausgeben RT1_FE2 LD DE,RAM_BD1 ; Adresse String -> DE LD HL,RT1_HLT ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben RT1_HLT HALT ; STOP JP RESET ; ; ;-------------------------------------------------- ; RAM Test 2 X 64K auf ELZET80 FDC-3 ; Finde FDC-3 RAMT02 LD DE,FDC3_FI ; Adr String -> DE, Finde FDC-3 LD HL,RT1_FDF ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben (DIRECT CALL) ; ; 1. Initialisiere FDC-3 - PIO ; RT1_FDF LD C,FD3PAC ; Initialisiere FDC-3 PIO-Port A LD A,F3PIOM3 ; MODE 3 OUT (C),A ; LD A,F3PAIOC ; I/O Control Word OUT (C),A ; LD A,F3PAINT ; Interrupt Control Word OUT (C),A ; LD A,F3PAMSK ; Interrupt Mask OUT (C),A ; LD C,FD3PAD ; LD A,0DFH ; FDC3-PIO-PORT A, Initial Value OUT (C),A ; ; LD C,FD3PBC ; Initialisiere FDC-3 PIO-Port B LD A,F3PIOM3 ; MODE 3 OUT (C),A ; LD A,F3PBIOC ; I/O Control Word OUT (C),A ; LD A,F3PBINT ; Interrupt Control Word OUT (C),A ; LD A,F3PBMSK ; Interrupt Mask OUT (C),A ; LD C,FD3PBD ; LD A,70H ; FDC3-PIO-PORT B, Initial Value OUT (C),A ; A19 - A16 = 0000 ; ; 2. Check if PIO Port B, Bit 3:0 is writable ; IN A,(C) ; Read PIO Port B AND 0F0H ; Clear Bit 3:0 (A19:A16) OR 09H ; Test Pattern XXXX 1001B OUT (C),A ; A19 - A16 = 9 NOP ; IN A,(C) ; Read PIO Port B LD B,A ; save in B AND 0FH ; Bit 3:0 only (A19:A16) CP 09H ; Port B Bit 3:0 = 9? JR NZ,FD3NOP ; NEIN, FDC-3 not Present LD A,B ; AND 0F0H ; Clear Bit 3:0 (A19:A16) OR 06H ; Test Pattern XXXX 0110B OUT (C),A ; A19 - A16 = 8 NOP ; IN A,(C) ; Read PIO Port B AND 0FH ; Bit 3:0 only (A19:A16) CP 06H ; Port B Bit 3:0 = 6? JR NZ,FD3NOP ; NEIN, FDC-3 not Present FD3_PRE LD A,70H ; FDC3-PIO-PORT B, Initial Value OUT (C),A ; A19 - A16 = 0000 LD DE,FDC3_PR ; JA, Adr String -> DE, FDC3 PRESENT LD HL,RT2_FDF ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben (DIRECT CALL) ; ; 3. Test FDC-3 DRAM Bank 0 from 1000H to START MINIMON ; RT2_FDF LD DE,FDC3_RT ; Text Message, RAM Test FDC-3 LD HL,RT2_RAT ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben (DIRECT CALL) RT2_RAT NOP ; RAM Test FDC-3 LD HL,DRAM_ST ; Start-Adresse DRAM LD DE,MFC00-1 ; Endadresse freies DRAM LD B,55H ; Testpattern -> B RT2_RBT LD A,B ; Testpattern -> A LD (HL),A ; Testpattern -> DRAM NOP ; LD A,(HL) ; Testpattern OK? CP B ; JR NZ,RT2_F01 ; NEIN -> Fehler INC HL ; nächste Adresse LD A,L ; Endadresse DRAM erreicht? OR A ; 256 Bytes Grenze? JR NZ,RT2_NBG ; nein LD SP,HL ; DRAM-Adressse in SP sichern LD HL,RT2_PLU ; Return-Adresse -> HL LD C,'+' ; Pluszeichen JP CHO_S0 ; ausgeben (DIRECT CALL) RT2_PLU LD HL,0000H ; restauriere DRAM-Adresse ADD HL,SP ; RT2_NBG LD A,L ; CP E ; Endadresse DRAM erreicht? JR NZ,RT2_RBT ; nein, teste nächstes Byte LD A,H ; Endadresse DRAM erreicht? CP D ; JR NZ,RT2_RBT ; nein, teste nächstes Byte LD DE,RAM_OK1 ; JA, RAM ist OK LD HL,RT2_RCT ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben (DIRECT CALL) RT2_RCT JR RT3_FDF ; Move Code to RAM ; FD3NOP LD A,70H ; FDC3-PIO-PORT B, Initial Value OUT (C),A ; A19 - A16 = 0000 LD DE,FDC3_NP ; Adr String -> DE, FDC3 NOT PRESENT LD HL,RT3_FDF ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben (DIRECT CALL) RT3_FDF JP MVTORAM ; RAM OK, Monitor -> Zieldresse im RAM ; ;-------------------------------------------------- ; ; RAM-Fehler ; ; DRAM on FDC3 ; ; BANK 0, ADR: 1000H - EFFFH ; IN HL = RAM-Adresse ; B = Write Data ; A = Read Data RT2_F01 EX DE,HL ; RAM-Adresse -> DE LD IY,RT2_FE2 ; IY = Return-Adr. JP RAM_FEH ; Fehleradr., Write Data und Read Data ausgeben RT2_FE2 LD DE,RAM_BD1 ; RAM Fehler LD HL,RT2_FE3 ; Return-Adresse -> HL JP TXTO_S0 ; Test ausgeben (DIRECT CALL) RT2_FE3 NOP ; Fehler JP MVTORAM ; ;-------------------------------------------------- ; Unterprogramme ohne Stack ;-------------------------------------------------- ; CHO_S0 gibt ASII-Character auf die serielle Schnittstelle 0 aus ; C = ASCII Character ; HL = Return Addresse ; REGISTER: C, HL CHO_S0 EX AF,AF' ; Save A in A' CHO_W0 LD A,SIO_WR0 ; OUT (SIOA_CTL),A ; Address Register RR0 IN A,(SIOA_CTL) ; Read RR0 AND SIO_TXE ; TX Empty ? JR Z,CHO_W0 ; NO, wait LD A,C ; Output Character OUT (SIOA_DAT),A ; EX AF,AF' ; Restore A JP (HL) ; Return ;-------------------------------------------------- ; TXTO_S0 gibt NULL-terminierten ASII-String auf die ; serielle Schnittstelle 0 aus ; DE = Adresse ASCII String ; HL = Return Addresse ; REGISTER: A, C, DE, HL ; TXTO_S0 LD A,(DE) ; Lade ASCCI Character OR A ; Endezeichen 00 erreicht? JR Z,TXTO_E ; ja, STOP LD C,A ; ASCII-Character -> C LD SP,HL ; Original Return-Adresse -> IX LD IX,0000H ; ADD IX,SP ; LD HL,TXTO_S1 ; Neue Return-Adresse -> HL JP CHO_S0 ; Character ausgeben, (CALL) TXTO_S1 LD SP,IX ; LD HL,0000H ; ADD HL,SP ; Return-Adresse -> HL LD SP,0100H ; Stackpointer auf Anfangswert INC DE ; naechster Character JR TXTO_S0 ; TXTO_E JP (HL) ; Return ;-------------------------------------------------- ; HXTOSP gibt SPACE auf Serial 0 aus, wandelt HEX-Datum in A in ASCII ; und gibt auf Serial 0 aus ; IN A = HEX-Datum ; IX = Return Adresse ; CHG REGISTER: A, B, C, HL, DE HXTOSP LD C,' ' ; Space -> C LD HL,HXTOS0 ; neue Return Adresse -> HL JP CHO_S0 ; SPACE -> Serial 0, (CALL DIRECT) ; ; weiter zum folgenden HXTOS0 ;-------------------------------------------------- ; HXTOS0 wandelt HEX-Datum in A in ASCII und gibt auf Serial 0 aus ; IN A = HEX-Datum ; IX = Return Addresse ; CHG REGISTER: A, B, C, HL, SP HXTOS0 EX DE,HL ; Sichere DE LD SP,HL ; in SP LD HL,HXTOSA ; Return Aresse - > HL JP HXTOAS ; konvertiere -> ASCII in DE, (CALL DIRECT) HXTOSA LD C,D ; High Nibble ASCII -> C LD HL,HXTOSB ; Return Adressse -> HL JP CHO_S0 ; High Nibble ASCII -> Serial 0, (CALL DIRECT) HXTOSB LD C,E ; Low Nibble ASCII -> C LD HL,HXTOSC ; Return Adressse -> HL JP CHO_S0 ; High Nibble ASCII -> Serial 0, (CALL DIRECT) HXTOSC LD HL,0000H ; Urspruengliche Return Adresse ADD HL,SP ; RESTORE EX DE,HL ; DE JP (IX) ; Return ;-------------------------------------------------- ; HXTOAS wandelt HEX-Datum in A in ASCII in D und E ; IN A = HEX-Datum ; HL = Return Addresse ; OUT DE = ASCII-Character ; CHG REGISTER: A, C, HL, DE HXTOAS LD C,A ; Sichere HEX-Wert in C AND 0FH ; LOW HEX Nibble CP 0AH ; SBC A,69H ; DAA ; LD E,A ; Low ASCII Nibble -> E LD A,C ; High HEX Nibble RRA ; RRA ; RRA ; RRA ; -> Bit 3:0 AND 0FH ; CP 0AH ; SBC A,69H ; DAA ; LD D,A ; High ASCII Nibble -> D JP (HL) ; Return ;-------------------------------------------------- ; Fehler RAM-Adresse ; Gebe Fehleradresse, Write Data und Read Data ; auf serielle Schnittstelle ; IN IY = Return-Adresse ; DE = RAM-Adresse ; B = Write Data ; A = Read Data ; REGS AF, AF', BC, DE, HL, IX, IY ;###### LD DE,1234H ; ###### DEBUG RAM_FEH LD I,A ; Read Data -> I LD C,'<' ; FEHLER, "<" ausgeben LD HL,RT0_FE2 ; Return-Adresse JP CHO_S0 ; auf Serial 0 ausgeben RT0_FE2 LD A,D ; High Byte Adresse -> A LD IX,RT0_FE3 ; Return-Adresse -> IX JP HXTOSP ; SPACE + HI-Byte ADR. -> Serial 0 RT0_FE3 LD A,E ; Low Byte Adresse -> A LD IX,RT0_FE4 ; Return-Adresse -> IX JP HXTOS0 ; LO-Byte ADR. -> Serial 0 RT0_FE4 LD A,B ; Write Data -> A LD IX,RT0_FE5 ; Return-Adresse -> IX JP HXTOSP ; SPACE + WRITE-Data -> Serial 0 RT0_FE5 LD A,I ; READ-Data -> A LD IX,RT0_FE6 ; Return-Adresse -> IX JP HXTOSP ; SPACE + READ-Data -> Serial RT0_FE6 LD C,' ' ; Space ausgeben LD HL,RT0_FE7 ; Return-Adresse -> HL JP CHO_S0 ; Space ausgeben RT0_FE7 JP (IY) ; RETURN ;-------------------------------------------------- MVTORAM LD DE,MOV_RAM ; Text "Move Code to RAM " ausgeben LD HL,MVTRRET ; Return Adresse -> HL JP TXTO_S0 ; Text ausgeben (CALL DIRECT) MVTRRET LD DE,STAMON ; Ziel-Adresse -> DE LD HL,ENDLOW ; Start-Adresse - HL LD BC,MO_END-STAMON ; Länge LDIR ; umkopieren NOP ; Check code im RAM LD HL,ENDLOW ; EPROM-Start ADR. -> HL LD IX,STAMON ; RAM Start-Adresse -> IX LD BC,MO_END-STAMON ; Länge -> BC MVNCHK LD A,(HL) ; EPROM DATUM -> A CP (IX+0) ; GLEICH EPROM DATUM ? JR NZ,MV_FAIL ; NEIN -> Fehler INC HL ; EPROM-Adresse +1 INC IX ; RAM-Adresse +1 DJNZ MVNCHK ; Teste nächstes Byte ; ; IMAGE im RAM ist OK LD DE,RAM_OK1 ; "OK" ausgeben LD HL,MVOKRET ; Return Adresse -> HL JP TXTO_S0 ; Text ausgeben (CALL DIRECT) MVOKRET LD HL,LD_OK ; Set Flag, Loaded to RAM LD (HL),055H ; INC HL ; LD (HL),0AAH ; JP STAMON ; Setze auf Zieladresse im RAM fort ; MV_FAIL JP RT1_FE1 ; Wie Fehler im RAM Test 1 ; ENDLOW DS 0 ; ; ;-------------------------------------------------- #IFDEF INTRAM ORG 0F000H ; ELZET80 IEC-CPU, Internal RAM #ELSE ORG 0FC00H ; STANDARD-CPU, BEREICH DER BUFFER #ENDIF ;-------------------------------------------------- ; MFC00 DS 0 ; Startaddresse RAM ; ;-------------------------------------------------- ; ORG 0FC30H ; STARTADR.DES MONITORS ;-------------------------------------------------- ; ; STACK DEFINIEREN STAMON LD SP,TOS ; ;-------------------------------------------------- ; Monitormeldung ausgeben LD HL,M0042 ; Adresse Monitormeldung CALL PRTXT ; Monitor-Meldung ausgeben ; INITIALISIEREN DES MONITORBUFFERS ; LD HL,BUFF ; LD B,10H ; BUFFER MIT '0' FUELLEN INIT XOR A ; LD (HL),A ; INC HL ; DJNZ INIT ; ;-------------------------------------------------- ; CURSOR EINSCHALTEN (BEI TRS-80) ; ; LD A,CON ; ; CALL CRT ; ; ;-------------------------------------------------- ; ; DRUCKT '-', LIEST ZEILE VOM KBD IN BUFF ; KBDL CALL CRLF ; neue Zeile LD A,'-' ; Aufforderungszeichen -> CRT CALL CRT ; ausgeben CALL PSP ; Space -> CRT CALL KBIN ; Warte auf Befehl, mit CR abgeschlossen PUSH HL ; save BUFF-Pointer LD HL,BUFF ; konvertiere ASCII -> Upper Case KBDL1 LD A,(HL) ; CP CR ; CR = Endezeichen JR Z,KBDLE ; JA -> Ende Konvertierung CP 'a' ; kleiner 'a' ? JR C,KBDNC ; -> do not change CP '{' ; größer 'z' ? JR NC,KBDNC ; -> do not change AND 01011111B ; Convert to Upper Case LD (HL),A ; save in Buffer KBDNC INC HL ; nächstes ASCII-Zeichen JR KBDL1 ; Continue KBDLE POP HL ; Restauriere Buff-Pointer ;-------------------------------------------------- ; SUCHT TABA NACH BEFEHL DURCH ; WENN GEFUNDEN SPRUNG JEXE ; EXEC LD HL,TABA ; Anfangsadresse Befehlstabelle XOR A ; ?? EXECl LD A,(BUFF) ; CP CR ; JR Z,KBDL ; NUR CR -> warte weiter auf Befehl CP (HL) ; Gültiger Befehl ? JR Z,JEXE ; Ja, weiter dekodieren LD A,0FFH ; Endezeichen CP (HL) ; der Befehls-Tabelle? JR Z,KBDL ; ja, warte weiter auf Befehl INC HL ; HL+3 INC HL ; nächstes Element der Tabelle INC HL ; JR EXECl ; ; ;-------------------------------------------------- ; SPRINGT ZU BEFEHLS ROUTINE ; JEXE PUSH HL ; Sichere BUFF-Zeiger CALL GETA ; Lese ARG1 und ARG2 POP HL ; Restauriere BUFF-Zeiger INC HL ; Nächstes Element in BUFF LD E,(HL) ; -> DE INC HL ; LD D,(HL) ; LD HL,KBDL ; Return-Adresse Hauptschleife PUSH HL ; -> Stack PUSH DE ; Adresse Monitor-Befehl -> Stack RET ; ausführen ;-------------------------------------------------- TABA DB 'M' ; DW MODIFY ; Modify Memory DB 'D' ; DW DISPM ; Display Memory (BIN) DB 'J' ; DW JUMP ; Goto Address DB 'B' ; DW BREP0 ; Set/RESET Breakpoint DB 'A' ; DW ASCII ; Display Memory (ASCII) DB 'I' ; DW INPU ; Input DB 'O' ; DW OUTP ; Output DB 'C' ; DW CLEARM ; Clear Memory DB 'P' ; DW PAGEM ; Memory Page DB 'T' ; DW TESTM ; Memory Test DB 0FFH ; Endezeichen ;-------------------------------------------------- ; UNTERPROG. LIEST (DE) U. WANDELT ASCII IN HEX ; ERGEBNIS STEHT IN AHEXB+1 AHEX XOR A ; AHEXB = 00 LD HL,AHEXB ; LD (HL),A ; INC HL ; LD (HL), A ; AHEXB+1 = 00 INC HL ; LD (HL),A ; AHEXB+2 = 00 AHEXl DEC HL ; Zeige auf AHEXB DEC HL ; LD A,(DE) ; ASCII -> A SUB 30H ; ASCII-Kontroll-Zeichen ? RET M ; JA -> UNGUELTIG CP 0AH ; ASCII 0 - 9 ? JR C,AHEX2 ; GUELTIG, 0-9 SUB 07H ; CP 0AH ; RET M ; UNGUELTIG CP 10H ; RET P ; UNGUELTIG AHEX2 INC DE ; INC (HL) ; INC HL ; RLD ; INC HL ; RLD ; JR AHEXl ; ; RLD ; zyklische Verschiebung nach links zwischen dem Akkumulator und dem Inhalt des durch HL ; adressiertem Speicherplatzes (m). ; Die unteren 4 Bit von m werden in die oberen 4 Bitstellen übertragen und diese ihrerseits ; in die unteren 4 Bits des Akkumulators. ; Die unteren 4 Bits des Akkumulators werden in die unteren 4 Bitstellen ; von m transportiert. Die oberen 4 Bits des Akkumulators bleiben unverändert. ;-------------------------------------------------- ; UNTERPROG. LIEST AUS EINGEG. ZEILE DIE ; ARGUMENTE ARG1 UND ARG2 ; GETA LD DE,BUFF+1 ; CALL TESP ; Suche Space CALL AHEX ; Wandle ASCII in HEX PUSH DE ; Sichere BUFF-Zeiger LD HL,AHEXB+1 ; Ergebnix in AHEXB+1 und AHEXB+2 LD E,(HL) ; Ergebnis -> DE INC HL ; LD D,(HL) ; LD (ARG1),DE ; Ergebnis -> ARG1 POP DE ; Restauriere BUFF-Zeiger CALL TESP ; Suche Space CALL AHEX ; Wandle ASCII in HEX LD HL,AHEXB+1 ; Ergebnix in AHEXB+1 und AHEXB+2 LD E,(HL) ; Ergebnis -> DE INC HL ; LD D,(HL) ; LD (ARG2),DE ; Ergebnis -> ARG2 RET ; ;-------------------------------------------------- ; UNTERPROG. SETZT DE UEBER SPACE ; Suche SPACE TESP XOR A ; LD A,(DE) ; CP ' ' ; RET NZ ; INC DE ; JR TESP ; ;-------------------------------------------------- ; UNTERPROG. DRUCKT AKKUINHALT IN HEX ; PRHEX PUSH AF ; RRA ; RRA ; RRA ; RRA ; CALL PRHEX1 ; POP AF ; PRHEX1 AND 0FH ; ADD A,30H ; CP ':' ; JR C,JCRT ; ADD A,07H ; JCRT JP CRT ; RETURN UEBER RET IN CRT ROUTINE ;-------------------------------------------------- ; ; UNTERPROG. DRUCKT CR/LF CRLF LD A,CR ; CALL CRT ; CR -> CRT LD A,LF ; JR JCRT ; LF -> CRT ;-------------------------------------------------- ; ; UNTERPROG. DRUCKT CR CRET LD A,CR ; JR JCRT ; ;-------------------------------------------------- ; UNTERPROG. DRUCKT SPACE PSP LD A,' ' ; JR JCRT ; ;-------------------------------------------------- ; UNTERPROG. DRUCKT ADRESSE IN HL PRHL PUSH DE ; Save DE, BC PUSH BC ; LD A,H ; Drucke Hex-Byte in H CALL PRHEX ; LD A,L ; CALL PRHEX ; Drucke Hex-Byte in L POP BC ; Restore DE, BC POP DE ; RET ; ;-------------------------------------------------- ; UNTERPROG. DRUCKT Zeichen in BC REGS LD A,B ; Register-Namen ausgeben CALL CRT ; LD A,C ; CALL CRT ; JR PSP ; Space ausgeben und RET ;-------------------------------------------------- ; UNTERPROG. DRUCKT ADRESSE IN HL und (HL) PR CALL PRHL ; HL als HEX -> Konsole CALL PSP ; LD A,'(' ; CALL CRT ; LD A,(HL) ; Adressierte Zelle -> Konsole CALL PRHEX ; LD A,')' ; CALL CRT ; CALL PSP ; Space JR CRLF ; CR + LF -> Konsole ;-------------------------------------------------- ; UNTERPROG. DRUCKT NULL terminierten ASCII-String ; HL = Pointer auf String PRTXT LD A,(HL) ; Lade ASCII Zeichen OR A ; NULL ? RET Z ; JA, Ende CALL CRT ; ausgeben INC HL ; nächstes Zeichen JR PRTXT ; ;-------------------------------------------------- ; UNTERPROG. KBD ABFRAGE, HL ZEIGT AUF BUFFER KBIN LD HL,BUFF ; KBIN1 XOR A ; CALL KBD ; Hole Zeichen CALL CRT ; ECHO to CRT LD (HL),A ; Zeichen -> Buffer LD A,L ; CP 0FH ; Ende Buffer erreicht? JR Z,KBIN3 ; JA -> ENDE LD A,(HL) ; Zeichen -> A INC HL ; erhöhe Zeiger CP BS ; Backspace ? JR NZ,KBIN2 ; nein DEC HL ; Backspace -> LD (HL),' ' ; Buffer wieder loeschen DEC HL ; LD (HL),' ' ; JR KBIN1 ; Warte auf naechstes Zeichen KBIN2 CP CR ; CR ? RET Z ; JA -> Ende Eingabe JR KBIN1 ; NEIN -> warte auf naechstes Zeichen KBIN3 LD A,CR ; LD (HL),A ; ENDE Buffer, mit CR abschliessen JR KBIN2 ; Ende Eingabe ;-------------------------------------------------- ; BEFEHLSROUTINEN ; ;-------------------------------------------------- ; SPRINGT ZU EINGEG. ADR. ; IN HL = Zieladresse ; JUMP LD HL,ARG1 ; LD E,(HL) ; INC HL ; LD D,(HL) ; PUSH DE ; RET ; ;-------------------------------------------------- ; HEXDUMP VON ADR1 - ADR2 ; im Original = TABU DISPM LD HL,(ARG1) ; HL = Anfangsadresse LD DE,(ARG2) ; DE = Endadresse CALL CRLF ; Neue Zeile TABU1 CALL PRHL ; Adresse ausgeben LD A,':' ; ':' ausgeben CALL CRT ; LD B,16 ; 16 Bytes pro Zeile TABU2 CALL PSP ; Space -> CRT LD A,(HL) ; CALL PRHEX ; Gebe Datum aus CALL CPHLDE ; Endadresse erreicht ? RET NC ; JA -> Return INC HL ; adressiere nächste Speicherzelle XOR A ; CALL KBDM ; Check Keyboard CP ' ' ; Space eingegeben? JR Z,TAWAIT ; JA -> anhalten bis nächstes SPACE CP ',' ; Komma eingegeben ? RET Z ; JA -> ENDE TABU3 DJNZ TABU2 ; nächstes Datum ausgeben CALL CRLF ; NEIN -> naechste Zeile JR TABU1 ; und weiter TAWAIT XOR A ; Warte auf SPACE CALL KBDM ; CP ' ' ; SPACE = weiter anzeigen JR Z,TABU3 ; JR TAWAIT ; ;-------------------------------------------------- ; AENDERT SPEICHERINHALT MODIFY LD HL,(ARG1) ; Lade Adresse MOD1 CALL CRLF ; neue Zeile CALL PRHL ; Adresse -> Console CALL PSP ; Space -> Console LD A,(HL) ; CALL PRHEX ; Datum -> Console CALL PSP ; Space -> Console PUSH HL ; CALL KBIN ; POP HL ; XOR A ; LD DE,BUFF ; LD A,(DE) ; CP CR ; JR NZ,MOD2 ; INC HL ; JR MOD1 ; MOD2 CP ',' ; Ende der Eingabe ? RET Z ; JA -> Return PUSH HL ; Save Adresse CALL AHEX ; wandle in HEX INC HL ; LD A,(HL) ; Restore Adresse POP HL ; LD (HL),A ; neues Datum -> Adresse INC HL ; nächste Adresse JR MOD1 ; ;-------------------------------------------------- ; SETZT (ARG1) "CALL BREAK" BREP0 XOR A ; LD A,(BUFF+1) ; CP CR ; JR Z,BREP01 ; LD BC,04H ; LD DE,BREBU ; LD HL,(ARG1) ; LDIR ; LD HL,(ARG1) ; LD (BREAD),HL ; LD (HL),0CDH ; INC HL ; LD DE,BREAK ; LD (HL),E ; INC HL ; LD (HL),D ; RET ; BREP01 LD BC,04H ; LD DE,(BREAD) ; LD HL,BREBU ; LDIR ; RET ; ;-------------------------------------------------- ; RETTET U. DRUCKT REGISTER, WIRD ; NACH BREAK ANGESPRUNGEN BREAK PUSH HL ; PUSH DE ; PUSH BC ; PUSH AF ; CALL CRLF ; neue Zeile POP HL ; AF -> HL LD B,'A' ; LD C,'F' ; CALL REGS ; Registernamen ausgeben CALL PR ; Register-Inhalt und adressiertes POP HL ; Byte ausgeben LD B,'B' ; LD C,'C' ; CALL REGS ; CALL PR ; POP HL ; LD B,'D' ; LD C,'E' ; CALL REGS ; CALL PR ; POP HL ; LD B,'H' ; LD C,'L' ; CALL REGS ; CALL PR ; ADRESSE IN HL und (HL) -> Console POP HL ; LD B,'P' ; LD C,'C' ; CALL REGS ; CALL PR ; ADRESSE IN HL und (HL) -> Console LD HL,0000H ; ADD HL,SP ; SP -> HL LD B,'S' ; LD C,'P' ; CALL REGS ; CALL PR ; RET ; ;-------------------------------------------------- ; ASCII-PRINT VON ADR1 - ADR2 ASCII LD HL,(ARG1) ; LD DE,(ARG2) ; Endadresse -> DE CALL CRLF ; neue Zeile ASCII1 CALL PRHL ; LD B,16 ; 16 Werte pro Zeile ASCII2 CALL PSP ; ;-------------------------------------------------- XOR A ; LD A,(HL) ; SBC A,20H ; TEST OB KLEINER SPACE LD A,20H ; JR C,ASCII5 ; ;-------------------------------------------------- LD A,(HL) ; SBC A,7AH ; TEST OB GROESSER Z JR C,ASCII4 ; LD A,20H ; JR ASCII5 ; ;-------------------------------------------------- ASCII4 LD A,(HL) ; ASCII5 CALL CRT ; CALL CPHLDE ; Endadresse erreicht ? RET NC ; JA -> Ende INC HL ; NEIN -> nächste Adresse XOR A ; CALL KBDM ; Tastatur-Eingabe CP ' ' ; Space ? JR Z,ASWAIT ; JA -> anhalten CP ',' ; Komma ? RET Z ; JA -> Ende ASCII6 DJNZ ASCII2 ; ; PUSH HL ; ; OR A ; ; LD DE,(ARG2) ; ; SBC HL,DE ; ; POP HL ; ; RET NC ; CALL CRLF ; neue Zeile JR ASCII1 ; ;-------------------------------------------------- ASWAIT XOR A ; CALL KBDM ; Tastatur-Eingabe CP ' ' ; Space ? JR Z,ASCII6 ; JR ASWAIT ; ;-------------------------------------------------- ; Im Original nicht enthaltene Kommandos ;-------------------------------------------------- ; ; INPUT: (I) (I/O-Adresse) ; INPU LD HL,(ARG1) ; Input from I/O-Device, neu CALL CRLF ; neue Zeile LD A,H ; 8-Bit I/O-Adresse, H = 00 ? OR A ; JR NZ,PARM_F ; nein -> Fehler LD A,L ; I/O-Adresse -> A CALL PRHEX ; I/O-Adresse ausgeben CALL PSP ; Space LD A,'=' ; '=' ausgeben CALL CRT ; CALL PSP ; Space LD C,L ; I/O-Adresse -> C IN A,(C) ; Lese -> A CALL PRHEX ; gebe aus RET ; PARM_F CALL CRLF ; neue Zeile LD A,'?' ; Parameter Fehler JP CRT ; ausgeben und RETURN (in CRT) ;-------------------------------------------------- ; ; OUTPUT: (O) (I/O-Adresse) (Datum) ; OUTP LD HL,(ARG1) ; Output to I/O-Device, neu CALL CRLF ; Neue Zeile LD A,H ; H = 00 ? OR A ; I/O-Adresse = 8 Bit ? JR NZ,PARM_F ; nein -> Fehler LD C,L ; OK, I/O-Adresse -> C LD HL,(ARG2) ; I/O-Wert -> HL LD A,H ; H = 00 ? OR A ; I/O-Wert = 8 Bit ? JR NZ,PARM_F ; nein -> Fehler LD A,L ; OK, I/O-Wert -> A OUT (C),A ; ausgeben RET ; ;-------------------------------------------------- ; ; Clear Memory: (C) (Anfangsadresse) (Endadresse) ; CLEARM LD DE,(ARG1) ; Clear Memory, Anfangsadresse CALL CRET ; CR ausgeben LD HL,(ARG2) ; Endadresse OR A ; Lösche Carry SBC HL,DE ; Länge -> BC LD B,H ; LD C,L ; LD HL,(ARG1) ; Anfangsadresse -> HL LD (HL),00H ; = 00 ; PUSH HL ; ### SAVE HL ; CALL PSP ; Gebe SPACE aus ; CALL PRHL ; ### Anfangsadresse ausgeben ; POP HL ; ### RESTORE HL ; LD D,H ; Zieladresse = HL + 1 LD E,L ; INC DE ; LDIR ; Clear Memory RET ; ;-------------------------------------------------- ; ; Memory Page: (P) (Page) {0 - F} ; PAGEM LD HL,(ARG1) ; Page CALL CRLF ; Neue Zeile LD A,H ; H = 00 ? OR A ; Page Nr. > 256 ? JR NZ,PARM_F ; JA -> Fehler LD A,L ; Page Nr. > 16 ? CP 10H ; JR NC,PARM_F ; JA -> Fehler LD C,FD3PBD ; FDC3, PIO-B Datenregister IN A,(C) ; Lese PIO-B, Bit 3:0, A19:A16 AND 0F0H ; Clear A19:A16 OR L ; Set A19:A16 OUT (C),A ; -> FDC-3 PIO Port B RET ; ;-------------------------------------------------- ; ; Test Memory: (T) (Anfangsadresse) (Endadresse) ; TESTM CALL CRLF ; neue Zeile LD DE,(ARG1) ; Test Memory, Anfangsadresse ; LD HL,0FFFH ; Anfangsadresse > 1000H ? ; OR A ; Lösche Carry ; SBC HL,DE ; Anfangsadresse < 1000H? ; JP NC,PARM_F ; Ja -> Parameter Fehler LD HL,(ARG2) ; Endadresse EX DE,HL ; -> DE LD HL,MFC00-1 ; unterhalb Monitor-Bereich? OR A ; Lösche Carry SBC HL,DE ; Endadresse < Monitor-Adresse ? JP C,PARM_F ; Ja -> Parameter Fehler LD HL,(ARG2) ; Endadresse -> HL LD DE,(ARG1) ; Anfangsadresse -> DE OR A ; Lösche Carry SBC HL,DE ; Anfangsadresse < Endadresse ? JP C,PARM_F ; Nein -> Parameter Fehler ; ; Adresstest ; schreibe Testpattern LD HL,(ARG1) ; Anfangsadresse -> HL LD DE,(ARG2) ; Endadresse -> DE TMADL1 LD A,H ; Schreibe High Byte Adressse LD (HL),A ; LD A,L ; INC HL ; Schreibe Low Byte Adresse LD (HL),A ; INC HL ; nächstes Adresspaar AND 0FEH ; 256 Byte Grenze JR NZ,TMADC1 ; nein, weiter PUSH AF ; save LD A,'.' ; '.' ausgeben CALL CRT ; -> Console POP AF ; restore TMADC1 CALL CPHLDE ; Anfangsadresse < Endadresse JR C,TMADL1 ; JA, nächstes Adresspaar ; Adresspattern initialisiert ; Prüfe Testpattern LD HL,(ARG1) ; Anfangsadresse -> HL LD DE,(ARG2) ; Endadresse -> DE TMADL2 LD B,(HL) ; Lade High Byte Adresse -> B INC HL ; Lade LOW Byte LD C,(HL) ; Adresse -> C DEC HL ; LD A,B ; High Byte Adresse CP H ; OK ? JR NZ,TMADF1 ; nein, Fehler HIGH Byte LD A,C ; Low Byte Adresse CP L ; OK ? JR NZ,TMADF2 ; nein, Fehler LOW-Byte LD A,C ; low Byte Adresse -> A AND 0FEH ; 256 Byte Grenze JR NZ,TMADC2 ; nein, weiter PUSH AF ; save LD A,'+' ; '+' ausgeben CALL CRT ; -> Console POP AF ; restore TMADC2 INC HL ; nächstes Adresspaar? INC HL ; CALL CPHLDE ; Anfangsadresse < Endadresse JR C,TMADL2 ; JA, nächstes Adresspaar ; ; RET ; Test OK, Return ; TMADF1 LD B,H ; Fehler HIGH-Byte, exp. Data -> B JR TMADF3 ; Adresse und Daten ausgeben TMADF2 LD B,L ; Fehler LOW-Byte, exp. Data -> B TMADF3 LD C,A ; Read Data -> C CALL CRLF ; neue Zeile CALL PRHL ; Adresse ausgeben LD HL,TMWTEX ; W = CALL PRTXT ; ausgeben LD A,B ; Expected Data CALL PRHEX ; ausgeben LD HL,TMRTEX ; R = CALL PRTXT ; ausgeben LD A,C ; Read Data CALL PRHEX ; ausgeben RET ; Return ; TMWTEX DB " W=",00H ; TMRTEX DB " R=",00H ; ;-------------------------------------------------- ; Im Original nicht enthaltene Unterprogramme ;-------------------------------------------------- ; CPHLDE ; IN HL = Start-Adresse ; IN DE = Endadresse ; OUT C = 1 -> Anfangsadresse < Endadresse ; OUT C = 0 -> Anfangsadresse >= Endadresse ; REGISTER: A CPHLDE PUSH HL ; Save HL SBC HL,DE ; Anfangsadresse - Endadresse POP HL ; Restore HL RET ;-------------------------------------------------- ; CRT gibt ASII-Character in A auf die serielle Schnittstelle 0 aus ; A = ASCII Character ; REGISTER: A CRT PUSH BC ; LD C,A ; rette Zeichen in C CRT1 LD A,SIO_WR0 ; OUT (SIOA_CTL),A ; Address Register RR0 IN A,(SIOA_CTL) ; Read RR0 AND SIO_TXE ; TX Empty ? JR Z,CRT1 ; NO, wait LD A,C ; Output Character OUT (SIOA_DAT),A ; POP BC ; RET ; Return ;-------------------------------------------------- ; KBDM Eine einmalige Abfrage der Tastatur. ; Das Zeichen steht im Akku. ; Wurde keine Taste gedrückt, ist der Akku ‘ 0 ’. ; IN - ; OUT A = 00 -> kein Zeichen, A <> 0 -> Eingabezeichen ; Z = 1 -> kein Zeichen ; Z = 0 -> Zeichen in A ; Register: A KBDM LD A,SIO_WR0 ; OUT (SIOA_CTL),A ; Address Register RR0 IN A,(SIOA_CTL) ; Read RR0 AND SIO_RXA ; RX Character available ? RET Z ; NEIN, Return mit Akku = 00 und Z = 1 IN A,(SIOA_DAT) ; Ja, Character einlesen OR A ; Z = 0 RET ; ;-------------------------------------------------- ; KBD liest ASII-Character von der seriellen Schnittstelle 0 ; IN - ; OUT A = ASCII Character KBD Call KBDM ; Character available ? OR A ; JR Z,KBD ; nein, warten IN A,(SIOA_DAT) ; Ja, Character einlesen RET ; und RETURN ;-------------------------------------------------- MO_END DB 0FFH ; ;-------------------------------------------------- ; RAM Speicherzellen BUFF DS 16 ; reserve 16 Bytes AHEXB DS 3 ; reserve 3 Bytes ARG1 DS 2 ; reserve 2 Bytes ARG2 DS 2 ; reserve 2 Bytes BREAD DS 2 ; reserve 2 Bytes BREBU DS 3 ; reserve 3 Bytes LD_OK DS 2 ; Flag, Monitor loaded to RAM TSTRAM DS 2 ; 1st. Memory TEST Loc. ; END