Die Firmware vom Futura Aquariencomputer ist für die Z80 CPU geschrieben worden. Ich habe sie ausgelesen und kommentiert. Der komplette Download auf GitHub.
; Futura Aquariencomputer ROM F- 1.89 (8K)
PRINT "Anfang..."
;Speicheraufteilung:
;0000h-1FFFh 8K EPROM
;2000h-27FFh 2K RAM
;4000h Uhrenchip mit 4 Bit Registern
;4000h : Register lesen (0Fh = Fehler)
;4001h : Register wählen
;4002h : Register-Schreiben
;Register: 4,5: Stunden (BCD); 2,3: Minuten (BCD); 0,1: Sekunden (BCD)
;6000h Keyboard-Spalte auf 0 zurücksetzen. Zeilendaten mit IN A,(00h) abfragen
;8000h Port-Adresse (0...2:frei, 3...9: Keyboard, 10...15: Display)
;A000h LED-Daten an gewähltes LED-Segment; (Port-Adresse zurücksetzen?)
;C000h Schreibzugriff => Watchdog zurücksetzen
;E000h Ausgangsport für die Steckdosen
ROMTop = 1FF0h ;bis hier wird die Prüfsumme berechnet
RAMBase = 2000h
RAMTop = 2800h ;Endadresse vom RAM + 1
NewVersion = 0 ;0 = Originalversion, 1 = neue Version
ORG RAMBase ;Basisadresse vom RAM. IX zeigt stets auf diese Adresse => (IX+d)
DisplayBufStart
KLED DEFS 2 ;LEDs der Tasten
; Bit
; 0 0:Tag-LED an
; 1 0:Nacht-LED an
; 2 0:Ein-LED an
; 3 0:Aus-LED an
; 4 0:Zeit-LED an
; 5 0:Momentan-LED an
; 6 0:Manuelle-LED an
; 7 0:Setzen-LED an
; Bit
; 0 0:pH-LED an
; 1 0:Temp-LED an
; 2 0:Leitwert-LED an
; 3 0:Redox-LED an
; 4 0:Kanal 1-LED an
; 5 0:Kanal 2-LED an
; 6 0:Licht-LED an
; 7 0:CO2-LED an
WarnLED DEFS 1 ;6 Warn-LEDs neben dem Display
; Bit
; 0 0:Kanal 2 an
; 1 0:CO2 an
; 2 0:ph-Alarm an
; 3 0:Kanal 1 an
; 4 0:Heizung an
; 5 0:Temp-Alarm an
; 6 unbenutzt
; 7 unbenutzt
DisplayBuf DEFS 6
DisplayBufEnd:
;Display-Buffer, wird bei jedem Mainloop-Durchlauf aus dem Display-RAM aufgebaut.
;Hier liegen die für die LEDs kodierten Zeichen drin.
;Font => LED-Tabelle
; 01
; --
;20 |40| 02 low-active!
; --
;10 | | 04
; -- .
; 08 80
Display DEFS 6 ;Display-RAM
;Zeichensatz im Display:
;00 - 0 01 - 1 02 - 2 03 - 3
;04 - 4 05 - 5 06 - 6 07 - 7
;08 - 8 09 - 9 0A - A 0B - B
;0C - C 0D - D 0E - E 0F - F
;10 - H 11 - L 12 - P 13 - r
;14 - U 15 - µ 16 - u 17 - n
;18 - ° 19 - o 1A - /F 1B - /A "/" = umgedrehter Buchstabe
;1C - - 1D - _ 1E - N 1F - Space
LastKey DEFS 1 ;zuletzt gedrückte Taste (FFh = keine)
Flags DEFS 1 ;diverse Flags
; Bit Aktion, wenn gesetzt
; 0 Zahleingabe an, ansonsten wird ein Wert dargestellt
; 1 zuletzt gedrückte Taste abgearbeitet. Wird erst gelöscht, wenn Taste losgelassen
; 2 Strom wurde eingeschaltet. Uhrzeit beim Einschalten blinkt.
; 3 Momentane Werte durchschalten
; 4 String im Display (0 = Zahl im Display)
; 5 (unbenutzt)
; 6 während der Kommunikation mit dem Hauptgerät (Meßwerte abholen)
; 7 Führende Zeichen aufgetreten. Nullen ab jetzt ausgeben.
DispLine DEFS 1 ;"Rasterzeile" beim Display-Refresh
DPunkt DEFS 1 ;Punkte im Display (Bit 0 = 6.Stelle, Bit 1 = 5.Stelle, ...)
BCDZahl DEFS 2 ;gewandelte BCD-Zahl
CO2EinZeit DEFS 3 ;Einschaltzeit von CO2
CO2AlarmZeit DEFS 3 ;Alarmzeit, wenn pH-Wert nicht den Sollwert erreicht hat
LichtEin DEFS 3 ;Uhrzeit, wann das Licht angeschaltet wird (3 Bytes: ss:mm:hh)
CO2Ein DEFS 3 ;Uhrzeit, wann das CO2 ausgeschaltet wird (3 Bytes: ss:mm:hh)
Mult24 DEFS 3 ;Multiplikator
Mult24Erg DEFS 3 ;Ergebnis der 24 Bit Multiplikation
LichtAus DEFS 3 ;Uhrzeit, wann das Licht ausgeschaltet wird (3 Bytes: ss:mm:hh)
CO2Aus DEFS 3 ;Uhrzeit, wann das CO2 ausgeschaltet wird (3 Bytes: ss:mm:hh)
TagZeit DEFS 3 ;Uhrzeit, wann der Tag beginnt (3 Bytes: ss:mm:hh)
SollTempTag DEFS 1 ;Temperatur für den Tag
NachtZeit DEFS 3 ;Uhrzeit, wann die Nacht beginnt (3 Bytes: ss:mm:hh)
SollTempNacht DEFS 1 ;Temperatur für die Nacht
ManuellZeit DEFS 3 ;Zeit, wie lange das Licht nach Druck auf "Manuell" an bleibt
SollpH DEFS 1 ;Soll-pH-Wert
MWpHLow DEFS 1 ;unteres Byte des Meßwertes
MWphHigh DEFS 1 ;oberes Byte des Meßwertes (nur 4 Bit)
IstpH DEFS 1 ;gemessener skalierter pH-Wert (obere 8 Bits des Meßwertes)
MWTempLow DEFS 1 ;unteres Byte des Meßwertes
MWTempHigh DEFS 1 ;oberes Byte des Meßwertes (nur 4 Bit)
IstTemp DEFS 1 ;gemessener skalierter Temp-Wert (obere 8 Bits des Meßwertes)
MWLeitwLow DEFS 1 ;unteres Byte des Meßwertes
MWLeitwHigh DEFS 1 ;oberes Byte des Meßwertes (nur 4 Bit)
IstLeitw DEFS 1 ;gemessener skalierter Leitwert-Wert (obere 8 Bits des Meßwertes)
MWRedoxLow DEFS 1 ;unteres Byte des Meßwertes
MWRedoxHigh DEFS 1 ;oberes Byte des Meßwertes (nur 4 Bit)
IstRedox DEFS 1 ;gemessener skalierter Redox-Wert (obere 8 Bits des Meßwertes)
Messcounter DEFS 1 ;Zähler von 16 abwärts; es wird nur alle 16 Durchläufe gemessen
TempTime DEFS 3 ;ss:mm:hh (temporäre Zeit während der Eingabeauswertung)
ManuellEinZeit DEFS 3 ;Zeit, wann "Manuell" gedrückt wurde
Counter DEFS 2 ;Blink-Timer (Bit 0 toggelt mit 0.5Hz; wird im IRQ abwärts gezählt)
Steckdosen DEFS 1 ;Steckdose (Bit = 1: Steckdose an)
; Bit Steckdose
; 0 CO2
; 1 Heizung
; 2 Licht
; 3 Kanal 1
; 4 Kanal 2
; 5,6,7 die oberen 3 Bits dienen der Kommunikation mit dem Hauptgerät
AktTime DEFS 3 ;aktuelle Uhrzeit (ss:mm:hh)
PowerOnZeit DEFS 3 ;Uhrzeit beim Einschalten des Stromes
ManuellAusZeit DEFS 3 ;Ausschaltzeit nach Druck auf "Manuell"
TempAlarmZeit DEFS 3 ;Heizungsalarm (Einschaltzeit + 1h)
DEFS 3
AktSchaltzeit DEFS 1 ;aktuelle Schaltzeit der Universaltimer (1...10 sind möglich)
SollLeitwertS DEFS 1 ;Soll-Leitwert (Süßwasser)
SollLeitwertM DEFS 1 ;Soll-Leitwert (Meerwasser)
Uni1Flag DEFS 1 ;55h => Kanal 1 = UNI-1
;AAh => Kanal 1 = Redox-Regler
;<> => Kanal 1 = inaktiv
Uni2Flag DEFS 1 ;55h => Kanal 2 = UNI-2
;AAh => Kanal 2 = Leitwert-Regler
;<> => Kanal 2 = inaktiv
Uni2Flag2 DEFS 1 ;55h = Leitwert EIN Regelung
;AAh = Leitwert AUS Regelung
SollRedox DEFS 1 ;Soll-Redoxwert
LeitwertKomp DEFS 1 ;kompensierter Leitwert
AktSollTemp DEFS 3 ;aktuelle Solltemperatur (Tag oder Nacht)
Kanal1Uni DEFS 11*2*3 ;Universaltimer-Zeiten von Kanal 1 (10 Stück a 3 Bytes, erst Ein-, dann Ausschaltzeiten)
Kanal2Uni DEFS 10*2*3 ;Universaltimer-Zeiten von Kanal 1 (10 Stück a 3 Bytes, erst Ein-, dann Ausschaltzeiten)
MomentanSek DEFS 1 ;Momentan-Sekunden-Merker für Momentan-Momentan
DelayTimer DEFS 1 ;Variable für Verzögerungen, etc.
KeyboardMatrix DEFS 7 ;Keyboard-Matrix-Zeilen (untere 4 Bit, gelöscht = gedrückt)
InputBuf: DEFS 10 ;Buffer für GetNumInput()
IF !NewVersion
LaufschriftFlag DEFS 1 ;55h = Laufschrift an
LaufschriftInit DEFS 1 ;55h = Laufschrift ist initialisiert
LaufschriftPtr DEFS 2 ;Ptr auf eine Laufschrift
ScrollPtr DEFS 2 ;Ptr auf das nächste Zeichen in der Laufschrift
ENDIF
SollChecksum DEFS 2 ;Soll-Prüfsumme über die Sollwerte
IF !NewVersion
DEFS 2
Dummy0: DEFS 2 ;= 0, wird in der Init-Laufschrift ausgegeben
ENDIF
AktROMChecksum DEFS 2 ;Prüfsumme über das ROM _während_ der Berechnung
CalcChecksum DEFS 2 ;letzte errechnete Prüfsumme
ChecksumFinal DEFS 1 ;Prüfsumme in CalcChecksum ist gültig (aber evtl. falsch!)
ROMTopAdr DEFS 2 ;Endadresse vom ROM (läuft bis 0 rückwärts während der Prüfsummenberechnung)
ErrorCode DEFS 1 ;aufgetretener Fehler (0 = keiner)
GesamtBZeit DEFS 5 ;Gesamt-Betriebsstunden
Kanal1BZeit DEFS 4 ;Betriebsstunden für Kanal 1 (4 Bytes: mm:hhhhhh)
Kanal2BZeit DEFS 4 ;Betriebsstunden für Kanal 2 (4 Bytes: mm:hhhhhh)
CO2BZeit DEFS 4 ;Betriebsstunden für CO2 (4 Bytes: mm:hhhhhh)
TempBZeit DEFS 4 ;Betriebsstunden für Heizung (4 Bytes: mm:hhhhhh)
LichtBZeit DEFS 4 ;Betriebsstunden für Licht (4 Bytes: mm:hhhhhh)
IF !NewVersion
StringBuf DEFS 200 ;???
StringBufPtr DEFS 2 ;???
InitLaufschr DEFS 1 ;0xAA = Init-Laufschrift an, 0x55 = Init-Laufschrift aus
InitLaufschrSek DEFS 1 ;Sekunden-Merker für den Init-Laufschrift-Start
Dummy DEFS 3 ;??? wird in der Init-Laufschrift ausgegeben, aber nie gesetzt
ENDIF
IF NewVersion
MomentanZeit DEFS 1 ;Weiterschaltzeit für Momentan (in Sekunden)
ENDIF
StackTop = RAMTop ;der Stack fängt ganz oben im RAM an
;Flags von: IN C,(C) (externe Schalter)
; 4 0:Programmiersperre an
; 5 0:Meerwasser, 1:Süßwasser
ORG 0000h
DI ;IRQs aus (an sich unnötig, sind nach einem Reset eh aus...)
IM 1 ;bei IRQs stets RST 38h ausführen!
LD SP,StackTop
LD (C000h),A
LD IX,RAMBase ;Basisadresse vom RAM
LD B,FFh
LD (IX+DispLine),DisplayBufEnd ;Display-Refresh (im IRQ)
IF !NewVersion
LD A,AAh
LD (InitLaufschr),A ;Init-Laufschrift AN
ENDIF
EI ;IRQs wieder an
LD HL,0
LD (AktROMChecksum),HL ;ROM-Prüfsumme zurücksetzen
LD HL,ROMTop
LD (ROMTopAdr),HL ;Endadresse vom ROM
JP Startup
ORG 0038h ;der RST 0x38 bzw. RST 7 Interrupt
DI
EXX
EX AF,AF'
JP DoIRQ
IF !NewVersion
JP DoIRQ ;???
ENDIF
ORG 0066h ;der NMI-Vektor des Z80
;NMI-Routine ("Reset" = alles zurücksetzen)
DoNMI: IF NewVersion
CALL ResetVars
RETN
ENDIF
;sämtliche Variablen zurücksetzen!
ResetVars: PUSH HL
PUSH AF
PUSH BC
PUSH DE
LD BC,23
LD HL,Kanal1BZeit
LD DE,Kanal1BZeit+1
LD (HL),0
LDIR ;Betriebszeiten löschen
LD DE,GesamtBZeit
LD HL,TempTime ;temp.Zeit übertragen
LD BC,3
LDIR ;Gesamtbetriebszeit setzen
IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
JR Z,DoNMI1 ;Meerwasser =>
LD A,64 ;Soll-pH-Wert ((64/2+38)/10 = 7.0)
JR DoNMI2
DoNMI1: LD A,90 ;(90/2+38)/10 = 8.3
DoNMI2: LD (IX+SollpH),A ;Soll-pH-Wert
LD A,145 ;(145+100)/10 = 24.5°
LD (IX+SollTempTag),A ;Soll-Temperatur (Tag)
LD A,130 ;(130+100)/10 = 23°
LD (IX+SollTempNacht),A ;Soll-Temperatur (Nacht)
LD A,150 ;150/10+35.0 = 50mS
LD (IX+SollLeitwertM),A ;Soll-Leitwert (Meerwasser)
LD A,80 ;80*10 = 800µS
LD (IX+SollLeitwertS),A ;Soll-Leitwert (Süßwasser)
LD A,125 ;125*2 = 250µV
LD (IX+SollRedox),A ;Soll-Redoxwert
LD A,0
LD (IX+AktSchaltzeit),A ;keine aktuelle Schaltzeit
LD (IX+Uni1Flag),A ;Kanal 1 inaktiv schalten
LD (IX+Uni2Flag),A ;Kanal 2 inaktiv schalten
LD (IX+Uni2Flag2),A ;Leitwert-Regelung inaktiv
LD HL,CO2Ein
LD B,3
DoNMI3: LD (HL),A ;CO2 Sperrzeit ein = 00.00.00
INC HL
DJNZ DoNMI3
LD HL,CO2Aus
LD B,3
DoNMI4: LD (HL),A ;CO2 Sperrzeit aus = 00.00.00
INC HL
DJNZ DoNMI4
IF NewVersion
LD A,7
LD (MomentanZeit),A ;Momentan-Zeit : 7 Sekunden
ENDIF
LD A,80h
LD (LichtEin+2),A
LD (TagZeit+2),A
LD A,81h
LD (LichtAus+2),A
LD (NachtZeit+2),A
POP DE
POP BC
POP AF
POP HL
IF NewVersion
RET
ELSE
RETN
ENDIF
;IRQ-Routine für Tastatur und Display
DoIRQ: LD A,0
LD (A000h),A ;Port-Adresse auf 0 zurücksetzen
LD HL,8000h
LD B,7 ;7 Keyboard-Spalten
LD DE,KeyboardMatrix+6
LD (HL),A
LD (HL),A ;auf Adresse 3 weiterschalten
LD (HL),A
LD (6000h),A ;Port auslesen
DoIRQ1: IN A,(00h) ;Keyboard-Spalte auslesen
LD (DE),A ;und merken
LD (HL),A qqww;Port-Adresse hochzählen
DEC DE ;eine Spalte nach vorne
DJNZ DoIRQ1 ;alle Spalten durch? Nein =>
LD B,(IX+DispLine) ;LED-Daten
DJNZ DoIRQ2 ;einmal durch?
LD B,DisplayBufEnd ;wieder von vorne
DoIRQ2: LD (IX+DispLine),B ;aktuelle Zeile setzen
LD H,DisplayBufStart>>8
LD L,B ;DisplayBuf + B - 1 (DisplayBuf...DisplayBufEnd)
DEC L
LD A,(HL) ;Speicherzelle aus dem Display auslesen
LD HL,8000h
DoIRQ3: LD (HL),A ;Port-Adresse hochzählen (10...15)
DJNZ DoIRQ3 ;und zwar B mal
CPL
LD (A000h),A ;und das Display-Segment setzen
LD HL,(Counter)
DEC HL ;IRQ-Zähler (für Display-Blinken)
LD (Counter),HL
EXX
EX AF,AF'
EI
RETI
Startup: LD (C000h),A
HALT ;Verzögerung
DJNZ Startup
LD HL,VersionNoDisp
LD DE,DisplayBuf
LD BC,6
LDIR ;Versionsnummer in die LED-Anzeige "F- 1.89"
LD B,FFh
Startup1: HALT
HALT
LD (C000h),A ;vierfache Verzögerung
HALT
HALT
LD (C000h),A
DJNZ Startup1
CALL KeyStern ;Display löschen
SET 2,(IX+Flags) ;PowerOn-Flag setzen
SET 6,(IX+KLED) ;Manuell-LED aus
LD DE,PowerOnZeit
LD HL,AktTime
LD BC,3
LDIR ;aktuelle Uhrzeit merken
IF !NewVersion
LD DE,StringBuf
LD (StringBufPtr),DE
LD HL,MsgEscHEscJ
CALL CopyString
LD HL,MsgMessdaten
CALL CopyString
LD A,55h
LD (InitLaufschr),A ;Init-Laufschrift AUS
JP DoLEDKonv
ENDIF
; Hier beginnt die Hauptschleife...
DoLEDKonv: LD B,6 ;6 LED-Anzeigen updaten
LD IY,Display ;Ptr auf Display-RAM (unkodiert)
LD HL,DisplayBuf
RES 7,(IX+Flags) ;noch kein 1.Zeichen ausgegeben
LD C,(IX+DPunkt) ;(6) Dezimalpunkte holen
SLA C
SLA C ;um 2 Bits nach oben an den "Byterand"
DoLEDKonv1: PUSH HL
LD HL,FontLEDTable ;Ptr auf "Zeichensatz"-Tabelle
LD E,(IY+0) ;Zeichen aus dem Display-RAM
LD D,0
ADD HL,DE
LD A,(HL) ;Zeichencode holen
SLA A ;A << 1
SLA C ;C << 1 (ins Carry)
RR A ;A >> 1; Carry in Bit 7
BIT 7,(IX+Flags) ;1.Zeichen schon ausgegeben?
JR NZ,DoLEDKonv3 ;Ja! =>
CP C0h ;"0"?
JR NZ,DoLEDKonv3 ;Nein => normal ausgeben
LD A,B
CP 1 ;letztes Anzeigeelement?
JR Z,DoLEDKonv2 ;Ja! =>
LD A,FFh ;LED komplett ausschalten (keine führenden Nullen ausgeben)(
JR DoLEDKonv4
DoLEDKonv2: LD A,C0h ;"0" darstellen
DoLEDKonv3: SET 7,(IX+Flags) ;1.Zeichen bereits ausgegeben
DoLEDKonv4: POP HL
LD (HL),A ;LED-Element neu setzen
INC IY ;weiter im Display-RAM
INC HL ;zum nächsten Element
DJNZ DoLEDKonv1 ;alle LEDs durch?
DoGetMess: LD B,(IX+Messcounter) ;alle 16 Durchläufe umrechnen?
DJNZ DoGetMess2 ;Nein! =>
LD B,4 ;4 Meßwerte holen (pH-Wert, Temperatur, Leitwert, Redox)
LD IY,MWpHLow
DoGetMess1: LD L,(IY+0) ;unteres Byte lesen
LD H,(IY+1) ;oberes Byte lesen
ADD HL,HL
ADD HL,HL
ADD HL,HL ;mal 8
ADD HL,HL
LD (IY+2),H ;nur das obere Byte merken
LD (IY+0),0 ;Meßwert zurücksetzen
LD (IY+1),0
INC IY ;zum nächsten Meßwert
INC IY
INC IY
DJNZ DoGetMess1
LD B,16 ;Durchlaufzähler neu setzen
DoGetMess2: LD (IX+Messcounter),B
LD HL,SpezKeyTable ;Ptr auf den Tabellenanfang
DoSpezKey: LD DE,KeyboardMatrix
LD B,7 ;7 Bytes pro Eintrag (= 7 Zeilen) (+ 2 Byte Adresse)
DoSpezKey1: LD A,(DE) ;Spaltenwert holen
OR F0h
CP (HL) ;Eintrag in der Tabelle?
JR Z,DoSpezKey3 ;Ja! => stimmen die nächsten 6 Bytes auch?
DoSpezKey2: INC HL
DJNZ DoSpezKey2 ;Eintrag überspringen
INC HL
INC HL
LD A,(HL) ;Folgebyte holen
CP 0 ;Tabellenende?
JR Z,DoKeyboard ;Ja! =>
JR DoSpezKey ;weiter vergleichen...
DoSpezKey3: INC DE ;nächste Tastaturspalte
INC HL
DJNZ DoSpezKey1 ;alle 7 Bytes gleich? Nein! => Weiter
LD D,(HL)
INC HL
LD E,(HL) ;Sprungadresse holen
PUSH DE ;Sprungadresse merken
POP IY
CALL CallIY ;gefundene Routine anspringen
DoKeyboard: LD A,0 ;Tastencode = 0
LD B,7 ;7 Tastaturspalten abklopfen
LD HL,KeyboardMatrix ;Ptr auf Tastaturmatrix-Basis
DoKeyboard1: LD C,4 ;maximal 4 Zeilen pro Spalte
LD D,(HL) ;Byte holen
DoKeyboard2: RR D
JR NC,DoKeyboard3 ;Bit gesetzt? (Taste gedrückt) => raus
INC A ;Tastencode++
DEC C ;alle Zeilen dieser Spalte zusammen?
JR NZ,DoKeyboard2 ;Nein =>
INC HL ;zur nächsten Spalte
LD (C000h),A
DJNZ DoKeyboard1 ;alle Spalten durch?
LD A,FFh ;dann keine Taste gedrückt
DoKeyboard3: CP (IX+LastKey) ;mit der zuletzt gedrückten Taste vergleichen
LD (IX+LastKey),A ;als letzte Taste merken
JR NZ,DoRecMess ;ungleich? => ignorieren (entprellen)
BIT 1,(IX+Flags) ;Taste abgearbeitet?
JR Z,DoKeyboard4 ;Nein =>
CP FFh ;keine Taste gedrückt?
JR NZ,DoRecMess ;doch! =>
RES 1,(IX+Flags) ;Abgearbeitet-Flag löschen
JR DoRecMess
DoKeyboard4: CP FFh ;keine Taste gedrückt?
JR Z,DoRecMess ;genau =>
SET 1,(IX+Flags) ;Taste abgearbeitet!
LD HL,TastaturTab ;Tastaturtabelle
ADD A,A
LD E,A
LD D,0
ADD HL,DE
LD D,(HL) ;Sonderflag
INC HL
LD E,(HL) ;Tastencode
BIT 7,D ;normale Ziffer?
JR Z,DoKeyboard6 ;Nein! =>
BIT 0,(IX+Flags) ;Zahleingabe an?
JR NZ,DoKeyboard5 ;Ja! =>
CALL KeyStern
SET 0,(IX+Flags) ;Zahleingabe an!
DoKeyboard5: LD A,E ;gedrückte Ziffer
LD BC,5
LD DE,Display
LD HL,Display+1
LDIR ;Display ein Zeichen nach links
LD (DE),A ;neues Zeichen einfügen
SCF ;Carry-Flag setzen
RL (IX+DPunkt) ;Punkte auch ein Zeichen nach links
LD (C000h),A
JR DoRecMess
DoKeyboard6: PUSH DE ;Sprungadresse merken
POP IY
CALL CallIY ;Sondertaste behandeln
;Meßwerte vom Hauptgerät empfangen
DoRecMess: LD B,4 ;4 Meßwerte
LD IY,MWRedoxLow ;Ptr auf den letzten Meßwert
LD (C000h),A
DoRecMess1: LD C,B
DEC C ;Meßwertnummer (0...3)
PUSH BC
CALL GetMesswert ;empfangen
POP BC
JR C,DoRecMess2 ;ok? Ja =>
PUSH BC
CALL GetMesswert ;nochmal probieren
POP BC
JR C,DoRecMess2 ;ok? Ja =>
LD A,82h
LD (ErrorCode),A ;Übertragungsfehler!
JR DoRecMess3 ;=> zum nächsten Meßwert
DoRecMess2: LD H,(IY+1) ;Highbyte vom Meßwert
LD L,(IY+0) ;Lowbyte vom Meßwert
LD E,A ;Meßwert dazuaddieren
LD D,0
ADD HL,DE
LD (IY+1),H ;Meßwert neu setzen
LD (IY+0),L
DoRecMess3: DEC IY
DEC IY
DEC IY
LD (C000h),A
DJNZ DoRecMess1 ;alle Meßwerte durch? Nein =>
;Uhrzeit (Uhrenchip liegt ab 4000h) auslesen
DoReadClock: LD IY,4000h ;Basisadresse des Uhrenchips
LD DE,AktTime+2 ;Ptr auf die Stunden der Uhrzeit
LD B,3 ;3 Werte (Stunden,Minuten,Sekunden)
LD C,5 ;mit Register 5 geht es los
HALT
DoReadClock1: LD (IY+1),C ;Register 5 auswählen
LD A,(IY+0) ;Register auslesen
AND 0Fh ;nur 4 Bit-Register!
CP 0Fh ;0Fh?
JR Z,DoReadClock3 ;Fehler =>
ADD A,A
ADD A,A
ADD A,A ;mal 16 + 0Fh
ADD A,A
OR 0Fh
DEC C
LD (IY+1),C ;Register 4 auswählen
AND (IY+0) ;unteren Teil der BCD-Zahl dazu
PUSH AF
AND 0Fh
CP 0Fh ;0Fh?
JR NZ,DoReadClock2 ;Nein => ok!
POP AF
JR DoReadClock3 ;Fehler =>
DoReadClock2: POP AF
LD (DE),A ;Stunden, Minuten, Sekunden merken
DEC DE ;eine Stelle weiter
DEC C ;Register 3,2 und dann Register 1,0
DJNZ DoReadClock1 ;alle Register durch? Nein =>
RES 7,(IX+AktTime+2) ;Uhrzeit fehlerfrei gelesen
JR DoErrorOut ;Ok =>
DoReadClock3: LD A,83h
LD (ErrorCode),A ;Fehler im interen Zeitschalter
DoErrorOut: LD (C000h),A
LD A,(ErrorCode) ;Fehlercode lesen
CP 0 ;kein Fehler?
JR Z,DoFlashResTime ;genau =>
LD E,A
JP ErrorOut
DoFlashResTime: BIT 2,(IX+Flags) ;PowerOn-Flag gesetzt?
JR Z,DoPrintTime ;Nein =>
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JP Z,EraseDisplay
LD HL,PowerOnZeit
CALL PrintTime ;Uhrzeit beim Einschalten ausgeben
JP DoLicht
DoPrintTime: BIT 5,(IX+KLED) ;"Zeit" an?
JP NZ,DoLicht ;Nein =>
BIT 4,(IX+KLED) ;"Momentan" an?
JR NZ,DoDispMess ;Nein =>
LD HL,AktTime
CALL PrintTime ;aktuelle Uhrzeit ausgeben
DoDispMess: LD B,4 ;4 Meßwerte
LD C,(IX+KLED+1) ;Meßwert-Tastatur-LED auslesen
LD E,11h ;mit Fehlermeldung 11 geht es los
LD HL,IstpH ;Ptr auf Ist-Wert vom pH-Wert
LD IY,DoDispMessTab ;Ptr auf Sprungtabelle für die verschiedenen Meßwerte
DoDispMess1: SRL C ;LED nach unten schieben
JR NC,DoDispMess2 ;LED an? => ja
INC HL
INC HL ;zum nächsten Meßwert
INC HL
INC IY ;ein Eintrag weiter in der Sprungtabelle
INC IY
INC E ;Fehlermeldung + 2
INC E
DJNZ DoDispMess1
JR DoLicht ;keinen Meßwert darstellen
DoDispMess2: LD A,(HL) ;Meßwert auslesen
CP 0 ;= 0?
JR Z,ErrorOut ;Meßbereich unterschritten =>
CP FFh
JR NZ,DoDispMess3 ;Meßbereich i.O. =>
INC E
JR ErrorOut ;Meßbereich überschritten =>
DoDispMess3: LD D,(IY+0) ;Sprungtabelle auslesen
LD E,(IY+1)
PUSH DE ;Sprungadresse merken
POP IY
LD L,A ;Meßwert / 2
SRL A
CALL CallIY ;gefundene Routine anspringen
JR DoLicht
CallIY: JP (IY)
;Fehlermeldung ausgeben, Fehlercode in E
ErrorOut: BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR NZ,ErrorOut1 ;An =>
EraseDisplay: LD HL,Display+5
LD DE,Display+4
LD BC,5
LD (HL),1Fh ;Display mit Leerzeichen füllen
LDDR
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
SET 4,(IX+Flags) ;keine Zahl im Display
JR DoLicht
ErrorOut1: LD A,E
CALL MakeErrCode
DoLicht: LD (C000h),A
LD HL,LichtEin
LD DE,LichtAus
CALL InTimeRange ;am Tage?
JR NC,DoLicht9 ;ja => Licht an
BIT 6,(IX+KLED) ;Manuell?
JR NZ,DoLicht8 ;Nein => Licht aus
LD HL,ManuellZeit ;Momentan-Timer-Wert (ss:mm:hh)
LD DE,ManuellEinZeit ;Zeit, wann "Manuell" gedrückt wurde
LD BC,ManuellAusZeit
LD A,(DE) ;Sekunden der Einschaltzeit
ADD A,(HL) ;+ Sekunden der Dauer
DAA
INC DE ;Ptr auf die Minuten
INC HL
JR NC,DoLicht2 ;ein Sekundenüberlauf? Nein =>
DoLicht1: SUB 60h ;Sekunden um 60 zurücksetzen
DAA
SCF ;Carry setzen (Sekunden-Übertrag)
JR DoLicht3
DoLicht2: CP 60h ;Sekunden-Überlauf?
JR NC,DoLicht1 ;Ja =>
CCF ;Nein, Carry löschen
DoLicht3: LD (BC),A ;Ausschaltzeit-Sekunden
INC BC
LD A,(DE)
ADC A,(HL) ;Ausschaltzeit-Minuten (+ Sekunden-Übertrag)
DAA
INC DE ;Ptr auf die Stunden
INC HL
JR NC,DoLicht5 ;ein Minutenüberlauf? Nein =>
DoLicht4: SUB 60h ;Minuten um 60 zurücksetzen
DAA
SCF ;Carry setzen (Minuten-Übertrag)
JR DoLicht6
DoLicht5: CP 60h ;Minuten-Überlauf?
JR NC,DoLicht4 ;Ja =>
CCF ;Nein, Carry löschen
DoLicht6: LD (BC),A ;Ausschaltzeit-Minuten
INC BC
LD A,(DE)
ADC A,(HL) ;Ausschaltzeit-Stunden (+ Minuten-Übertrag)
DAA
CP 24h ;24h Überlauf?
JR C,DoLicht7 ;Nein =>
SUB 24h ;Uhrzeit des nächsten Tages
DAA
DoLicht7: LD (BC),A ;Aussschaltzeit-Stunden
LD HL,ManuellEinZeit
LD DE,ManuellAusZeit
CALL InTimeRange ;im "Manuell"-Einschaltzeitraum?
JR NC,DoLicht9 ;Ja => Licht an
SET 6,(IX+KLED) ;Manuell aus
DoLicht8: RES 2,(IX+Steckdosen) ;Licht aus
JR DoKanal1
DoLicht9: SET 2,(IX+Steckdosen) ;Licht an
DoKanal1: LD HL,Kanal1Uni ;Einschaltzeiten
LD DE,Kanal1Uni+30 ;Ausschaltzeiten
CALL Kanal1Regel
JR C,DoKanal11
SET 3,(IX+Steckdosen) ;Kanal 1 an
RES 3,(IX+WarnLED) ;Kanal 1-LED an
JR DoKanal2
DoKanal11: RES 3,(IX+Steckdosen) ;Kanal 1 aus
SET 3,(IX+WarnLED) ;Kanal 1-LED aus
DoKanal2: LD HL,Kanal2Uni ;Einschaltzeiten
LD DE,Kanal2Uni+30 ;Ausschaltzeiten
CALL Kanal2Regel
JR C,DoKanal21
SET 4,(IX+Steckdosen) ;Kanal 2 an
RES 0,(IX+WarnLED) ;Kanal 2-LED an
JR DoTemp
DoKanal21: RES 4,(IX+Steckdosen) ;Kanal 2 aus
SET 0,(IX+WarnLED) ;Kanal 2-LED aus
DoTemp: LD HL,TagZeit
LD DE,NachtZeit
CALL InTimeRange ;ist es Tag?
JR C,DoTemp1 ;Nein =>
LD A,(IX+SollTempTag) ;Soll-Temperatur (Tag)
JR DoTemp2
DoTemp1: LD A,(IX+SollTempNacht) ;Soll-Temperatur (Nacht)
DoTemp2: PUSH AF ;Soll-Temperatur merken
LD (IX+AktSollTemp),A ;aktuelle Soll-Temperatur merken
BIT 4,(IX+WarnLED) ;Heizung-LED an?
JR Z,DoTemp6 ;Ja! => Heizung regeln
CP (IX+IstTemp) ;Ist-Temp-Wert >= Soll-Temperatur?
JR C,DoTemp4 ;Ja! => Heizung ausschalten
SET 1,(IX+Steckdosen) ;Heizung an
RES 4,(IX+WarnLED) ;Heizung-LED an
LD HL,AktTime
LD DE,TempAlarmZeit
LD BC,3
LDIR ;Einschaltzeit der Heizung merken
DEC DE
LD A,(DE) ;Stunden holen
INC A ;+1
CP 24h ;24 Uhr?
JR C,DoTemp3 ;kleiner als 24 Uhr? Ja =>
LD A,0 ;0 Uhr annehmen
DoTemp3: LD (DE),A ;Stunden setzen
POP AF
JR DoTemp10
DoTemp4: POP AF
SET 5,(IX+WarnLED) ;Temp.Alarm aus
DoTemp5: SET 4,(IX+WarnLED) ;Heizung-LED aus
RES 1,(IX+Steckdosen) ;Heizung aus
JR DoTemp10
DoTemp6: LD HL,AktTime
LD DE,TempAlarmZeit
CALL CompareTimes ;eine Stunde heizen um?
JR NC,DoTemp7 ;Nein =>
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DoTemp7 ;Nein =>
RES 5,(IX+WarnLED) ;Temp.Alarm an
JR DoTemp8
DoTemp7: SET 5,(IX+WarnLED) ;Temp.Alarm aus
DoTemp8: POP AF ;Soll-Temperatur wieder vom Stack holen
ADD A,1
CP (IX+IstTemp) ;Ist-Temp-Wert >= Soll-Temp + 0.1°?
JR C,DoTemp5 ;Ja =>
SET 1,(IX+Steckdosen) ;Heizung an
DoTemp10: LD A,(IX+IstTemp) ;Ist-Temp-Wert
SUB 8
CP (IX+AktSollTemp) ;Soll-Temp >= Ist-Temp - 0.8°? (Temperatur zu kalt?)
JR C,DoPh ;Ja =>
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DoTemp11 ;Nein =>
SET 5,(IX+WarnLED) ;Temp.Alarm aus
JR DoPh
DoTemp11: RES 5,(IX+WarnLED) ;Temp.Alarm an
DoPh: LD (C000h),A
LD B,(IX+IstpH) ;Ist-pH-Wert
SRL B
PUSH BC
LD HL,CO2Ein
LD DE,CO2Aus
CALL InTimeRange ;CO2-Sperrzeit?
JR C,DoPh2 ;Ja =>
BIT 1,(IX+WarnLED) ;CO2-LED an?
JR Z,DoPh4 ;Ja! =>
LD A,(IX+SollpH) ;Soll-pH-Wert
POP BC
CP B ;>= Ist-pH-Wert?
JR NC,DoPh3 ;zu groß =>
RES 1,(IX+WarnLED) ;CO2-LED an
SET 0,(IX+Steckdosen) ;CO2 an
LD HL,AktTime
LD DE,CO2EinZeit
LD BC,3
LDIR ;Einschaltzeit des CO2
LD HL,AktTime
LD BC,3
LDIR ;Alarmzeit des CO2
DEC DE
LD A,(DE)
ADD A,3 ;= Einschaltzeit + 3h
DAA
CP 24h ;24h Überlauf?
JR C,DoPh1 ;Nein =>
SUB 24h ;- 24h
DoPh1: LD (DE),A
JR DoPh7
DoPh2: POP BC
DoPh3: SET 2,(IX+WarnLED) ;CO2-Alarm aus
SET 1,(IX+WarnLED) ;CO2-LED aus
RES 0,(IX+Steckdosen) ;CO2 aus
JR DoPh7
DoPh4: LD HL,CO2EinZeit
LD DE,CO2AlarmZeit
CALL InTimeRange ;CO2 schon 3h an?
JR NC,DoPh5 ;Nein =>
LD A,(IX+IstpH) ;Ist-pH-Wert
SRL A
CP (IX+SollpH) ;= Soll-pH-Wert
JR Z,DoPh5 ;Ja => (kein Alarm)
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DoPh5
RES 2,(IX+WarnLED) ;pH-Alarm an
JR DoPh6
DoPh5: SET 2,(IX+WarnLED) ;pH-Alarm aus
DoPh6: LD A,(IX+SollpH) ;Soll-pH-Wert
SUB 1 ;- 0.05
POP BC
CP B ;=> Ist-pH-Wert? (Vergleich: Ist-pH-Wert < Soll-pH-Wert)
JR NC,DoPh3 ;zu groß => CO2 aus
DoPh7: LD A,(IX+IstpH) ;Ist-pH-Wert
SRL A
ADD A,6 ;+ 0.3
CP (IX+SollpH) ;Soll-pH-Wert (Ist-pH-Wert <= Soll-pH-Wert + 0.35)
JR NC,DoMomentan
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DoPh8
SET 2,(IX+WarnLED) ;pH-Alarm aus
JR DoMomentan
DoPh8: RES 2,(IX+WarnLED) ;pH-Alarm an
DoMomentan: CALL TempKomp ;Leitwert mit der Temperatur kompensieren
LD (C000h),A
BIT 5,(IX+KLED) ;"Momentan" an?
JR NZ,DoLaufschr ;Nein =>
BIT 3,(IX+Flags) ;Momentane Werte durchschalten?
JR Z,DoLaufschr ;Nein =>
LD HL,MomentanSek
LD A,(AktTime) ;Sekunden beim letzten Durchlauf
CP (HL) ;Sekunden geändert?
JR Z,DoLaufschr ;Nein =>
LD (HL),A ;letzten Sekundenstand merken
LD HL,DelayTimer ;Pause für die Darstellung
LD A,(HL)
INC A
IF NewVersion
PUSH HL
LD HL,MomentanZeit
CP (HL) ;Momentane Sekunden abgelaufen?
POP HL
ELSE
CP 7 ;7 Sekunden darstellen
ENDIF
JR C,DoMomentan4 ;Zeit abgelaufen? Nein =>
LD A,(IX+KLED+1) ;LEDs rechte Spalte auslesen
OR F0h
CP FFh ;alle LEDs aus?
JR NZ,DoMomentan1 ;Nein =>
SET 4,(IX+KLED) ;Uhrzeit ausschalten
RES 0,(IX+KLED+1) ;pH-Wert anschalten
JR DoMomentan3
DoMomentan1: RLCA ;Anzeige weiterschalten
BIT 4,A ;Überlauf?
JR NZ,DoMomentan2 ;Nein =>
LD A,(IX+KLED+1)
OR 0Fh ;rechte Spalte ausschalten
LD (IX+KLED+1),A
RES 4,(IX+KLED) ;Uhrzeit anschalten
JR DoMomentan3
DoMomentan2: LD B,A ;rotierte Matrix merken
LD A,(IX+KLED+1) ;rechte Spalte erneut auslesen
OR 0Fh ;alle LEDs aus
AND B ;rotierte Matrix dazu
LD (IX+KLED+1),A ;und neue LEDs anschalten
DoMomentan3: LD A,0 ;Pause wieder zurücksetzen
DoMomentan4: LD (HL),A ;Delay-Timer setzen
DoLaufschr: IF !NewVersion
LD (C000h),A
LD A,(LaufschriftFlag)
CP 55h
JR NZ,DoSollChecksum ;keine Laufschrift =>
LD A,(LaufschriftInit)
CP 55h ;Laufschrift initialisiert?
JR Z,DoLaufschr1 ;Ja =>
LD HL,(LaufschriftPtr)
LD (ScrollPtr),HL ;Laufschrift-Text setzen
LD A,55h
LD (LaufschriftInit),A ;aktiv schalten
LD (IX+KLED),FFh ;alle Tasten-LEDs aus
LD (IX+KLED+1),FFh
DoLaufschr1: LD A,(DelayTimer)
DEC A ;DelayTimer runterzählen
LD (DelayTimer),A
JR NZ,DoSollChecksum ;noch nicht abgelaufen =>
LD A,12
LD (DelayTimer),A ;DelayTimer neu setzen
LD HL,(ScrollPtr)
LD A,(HL) ;nächstes Zeichen aus dem Scrollstring
INC HL
LD (ScrollPtr),HL
CP 40h ;"Display löschen"? (Stringanfang)
JR NZ,DoLaufschr3 ;Nein! =>
LD HL,Display ;Display löschen
LD B,6
DoLaufschr2: LD (HL),1Fh ;Leerzeichen
INC HL
DJNZ DoLaufschr2
JR DoSollChecksum
DoLaufschr3: CP 42h ;"Leerzeichen (langsam)"?
JR Z,DoLaufschr4 ;Ja! =>
CP 41h ;Neustart vom Anfang an? (Stringende)
JR NZ,DoLaufschr5 ;Nein! =>
LD HL,(LaufschriftPtr)
LD (ScrollPtr),HL
LD A,80
LD (DelayTimer),A ;6.7-fache Pause vorher einlegen
JR DoSollChecksum ;nix ausgeben =>
DoLaufschr4: LD A,48
LD (DelayTimer),A ;4-fache Pause
LD A,1Fh ;Leerzeichen ausgeben
DoLaufschr5: LD (IX+DPunkt),FFh ;Dezimalpunkte aus
LD (IX+KLED),FFh ;alle Tasten-LEDs aus
LD (IX+KLED+1),FFh
LD DE,Display
LD HL,Display+1
LD BC,5
LDIR ;nach links scrollen
LD (DE),A ;neues Zeichen einfügen
ENDIF
DoSollChecksum: LD (C000h),A
CALL CalcSollChecksum ;Prüfsumme über die Sollwerte errechnen
LD HL,(SollChecksum) ;alte Prüfsumme holen
XOR A ;kein Fehler
SBC HL,DE ;Prüfsummen gleich?
JR Z,DoBetrStd ;Ja! =>
LD (SollChecksum),DE ;als neue Prüfsumme merken
LD A,80h ;Prüfsumme über die Sollwerte geändert!
LD (ErrorCode),A
DoBetrStd: LD (C000h),A
LD A,(IX+AktTime+2) ;aktuelle Stunden
LD HL,GesamtBZeit+3
CP (HL) ;= Gesamtzeitstunden (low-Byte der Stunden)
JR Z,DoBetrStd1 ;Ja =>
LD (HL),A
LD HL,GesamtBZeit
CALL IncHour ;Gesamtzeit um eine Stunde erhöhen
DoBetrStd1: LD A,(IX+AktTime+1) ;aktuelle Minuten
LD HL,GesamtBZeit+4
CP (HL) ;= Gesamtzeitminuten
JR Z,DoInitStr ;Ja => (noch keine Minute rum)
LD (HL),A ;neue Minuten merken
BIT 3,(IX+WarnLED) ;Kanal 1-LED an?
JR NZ,DoBetrStd2 ;Nein =>
LD HL,Kanal1BZeit
CALL IncMinute
DoBetrStd2: BIT 0,(IX+WarnLED) ;Kanal 2-LED an?
JR NZ,DoBetrStd3 ;Nein =>
LD HL,Kanal2BZeit
CALL IncMinute
DoBetrStd3: BIT 1,(IX+WarnLED) ;CO2-LED an?
JR NZ,DoBetrStd4 ;Nein =>
LD HL,CO2BZeit
CALL IncMinute
DoBetrStd4: BIT 4,(IX+WarnLED) ;Heizung-LED an?
JR NZ,DoBetrStd5 ;Nein =>
LD HL,TempBZeit
CALL IncMinute
DoBetrStd5: BIT 2,(IX+Steckdosen) ;Licht an?
JR Z,DoInitStr ;Nein =>
LD HL,LichtBZeit
CALL IncMinute
DoInitStr: IF !NewVersion
LD (C000h),A
LD HL,InitLaufschrSek
LD A,(AktTime) ;Sekunden auslesen
CP (HL)
JP Z,DoROMChksum ;gleich der gemerkten Sekunden? =>
LD (HL),A
LD A,(InitLaufschr) ;Init-Laufschrift?
CP 55h
JP Z,DoROMChksum ;gleich =>
LD IY,Dummy0
LD (IY+0),0 ;???
LD (IY+1),0
LD DE,StringBuf
LD A,2
LD (DE),A
INC DE
LD HL,AktTime
LD B,3
DoInitStr1: LD A,(HL)
CALL HexByteOut ;Uhrzeit ausgeben
INC HL
DJNZ DoInitStr1
LD A,' '
LD (DE),A
INC DE
LD HL,Dummy ;???
LD B,3
DoInitStr2: LD A,(HL)
CALL HexByteOut
INC HL
DJNZ DoInitStr2
LD A,' '
LD (DE),A
INC DE
LD A,(IX+IstpH) ;Ist-pH-Wert
SRL A
CALL HexByteOut
LD A,' '
LD (DE),A
INC DE
LD A,(IX+IstTemp) ;Ist-Temp-Wert
CALL HexByteOut
LD A,' '
LD (DE),A
INC DE
LD A,(IX+LeitwertKomp) ;kompensierter Leitwert
CALL HexByteOut
LD A,' '
LD (DE),A
INC DE
LD A,(IX+IstRedox) ;Ist-Redox-Wert
CALL HexByteOut
LD A,' '
LD (DE),A
INC DE
IN A,(C)
AND 20h ;Süßwasser/Meerwasser-Schalter
LD B,A
LD A,(IX+Steckdosen) ;Steckdosen-Status
AND 1Fh
OR B
CALL HexByteOut
LD A,' '
LD (DE),A
INC DE
LD HL,(Dummy0) ;= 0
LD A,H
CALL HexByteOut
LD A,L
CALL HexByteOut
LD A,13
LD (DE),A
INC DE
LD A,3
LD (DE),A
LD HL,StringBuf
LD (StringBufPtr),HL
LD A,55h
LD (InitLaufschr),A ;Init-Laufschrift AUS
ENDIF
;Prüfsummenberechnung über das ROM
DoROMChksum: LD (C000h),A
LD DE,(AktROMChecksum) ;alte Prüfsumme lesen
LD HL,(ROMTopAdr) ;Endadresse vom ROM - 1
DEC HL
LD (ROMTopAdr),HL ;Endadresse - 1
LD A,L
OR H ;Adresse zusammen"OR"n
LD L,(HL) ;Speicherstelle auslesen
LD H,00h
ADD HL,DE ;alte Prüfsumme dazuaddieren
LD (AktROMChecksum),HL ;Prüfsumme neu merken
CP 00h ;Anfang vom ROM erreicht?
JR NZ,DoMainloop ;Nein =>
LD HL,(AktROMChecksum) ;Prüfsumme auslesen
LD (CalcChecksum),HL ;errechnete Prüfsumme merken
LD A,0
LD (ChecksumFinal),A
LD DE,(ROMChecksum) ;erwartete Prüfsumme
XOR A
SBC HL,DE ;Prüfsumme gleich?
JR Z,DoROMChksum1 ;Ja! =>
LD A,81h ;Programmstörung!
LD (ErrorCode),A
DoROMChksum1: LD HL,0
LD (AktROMChecksum),HL ;alte Prüfsumme zurücksetzen
LD HL,ROMTop
LD (ROMTopAdr),HL ;Ende vom ROM neu setzen
DoMainloop: LD (C000h),A
JP DoLEDKonv ;und wieder von vorne...
; Unbenutzer Code:
IF !NewVersion
DoComm: LD A,(IX+Steckdosen) ;Steckdoses-Status
RES 5,A
CALL DoComm4 ;0??
LD B,7
DoComm1: RR C
JR C,DoComm2 ;8 Bits übertragen
RES 5,A
JR DoComm3
DoComm2: SET 5,A
DoComm3: CALL DoComm4
DJNZ DoComm1
PUSH HL
POP HL
SET 5,A
LD (E000h),A ;1??
RET
DoComm4: LD (E000h),A
NOP
NOP
NOP
RET
ENDIF
;Hexbyte nach DE schreiben. (IY+0/1) enthält die Prüfsumme
IF !NewVersion
HexByteOut:
PUSH AF
SRL A
SRL A
SRL A
SRL A
CALL HexByteOut1
POP AF
AND 0Fh
HexByteOut1: CP 10 ;größer als 10?
JR C,HexByteOut2 ;Nein! =>
ADD A,'7' ;+ '7' = 'A'...'F'
JR HexByteOut3
HexByteOut2: ADD A,'0' ;sonst + '0' = '0'...'9'
HexByteOut3: LD (DE),A ;in den Buffer schreiben
INC DE
ADD A,(IY+0) ;alte Summe dazuaddieren
LD (IY+0),A ;als neue Summe merken
LD (C000h),A
RET NC ;Überlauf der Prüfsumme? Nein => raus
INC (IY+1) ;Prüfsummen-Highbyte hochzählen
RET
ENDIF
; String ab HL nach DE bis zum "$" kopieren
IF !NewVersion
CopyString:
LD (C000h),A
LD A,(HL) ;Zeichen aus dem String holen
CP '$' ;Textende erkannt?
RET Z ;dann raus =>
LD (DE),A ;Zeichen übertragen
INC DE
INC HL
JR CopyString
; String mit Fehlermeldung in HL (zwei ASCII-Zeichen) zusammensetzen
ErrorString:
PUSH HL
LD HL,MsgFehl ;"FEHL." ausgeben
CALL CopyString
POP HL
LD A,H
LD (DE),A ;Fehlernummer übertragen
INC DE
LD A,L
LD (DE),A
INC DE
LD HL,Msg6Space ;" ",13,10,10 anhängen
CALL CopyString
RET
; "." an den String anhängen
ConcatPunkt: EX DE,HL
LD (HL),'.'
EX DE,HL
INC DE
RET
ENDIF
; Prüfsumme über die Sollwerte berechnen, Ergebnis nach DE
CalcSollChecksum:
PUSH HL
LD HL,0
LD D,0
LD E,(IX+SollpH) ;Soll-pH-Wert
ADD HL,DE
LD E,(IX+SollTempTag) ;Soll-Temperatur (Tag)
ADD HL,DE
LD E,(IX+SollTempNacht) ;Soll-Temperatur (Nacht)
ADD HL,DE
LD E,(IX+SollLeitwertS) ;Soll-Leitwert (Süßwasser)
ADD HL,DE
LD E,(IX+SollLeitwertM) ;Soll-Leitwert (Meerwasser)
ADD HL,DE
LD E,(IX+SollRedox) ;Soll-Redoxwert
ADD HL,DE
EX DE,HL
POP HL
LD (C000h),A
RET
;langer Timer (1 Byte Minuten, 3 Bytes Stunden) um eine Minute erhöhen
IncMinute: LD A,(HL)
INC A
CP 60 ;Sekundenüberlauf?
JR C,IncMinute1 ;Nein =>
LD (HL),0 ;Sekunden auf 0 zurücksetzen
INC HL
JR IncHour
IncMinute1: LD (HL),A
RET
IncHour: LD B,3 ;3 Bytes für Stunden
IncHour1: LD A,(HL)
ADD A,1 ;Stunden um eins erhöhen
DAA
LD (HL),A
JR NC,IncHour2
INC HL
DJNZ IncHour1
IncHour2: RET
;"Zeit" gedrückt
KeyZeit: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED) ;Tastenlampen holen
BIT 4,A ;Zeit war bereits an?
JR NZ,KeyZeit6 ;Nein =>
BIT 4,(IX+KLED+1) ;"Kanal 1"
JR NZ,KeyZeit1 ;Nein =>
LD HL,Kanal1BZeit+1
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
KeyZeit1: BIT 5,(IX+KLED+1) ;"Kanal 2"
JR NZ,KeyZeit2 ;Nein =>
LD HL,Kanal2BZeit+1
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
KeyZeit2: BIT 7,(IX+KLED+1) ;"CO2"
JR NZ,KeyZeit3 ;Nein =>
LD HL,CO2BZeit+1
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
KeyZeit3: BIT 6,(IX+KLED+1) ;"Licht"
JR NZ,KeyZeit4 ;Nein =>
LD HL,LichtBZeit+1
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
KeyZeit4: BIT 1,(IX+KLED+1) ;"Temperatur"
JR NZ,KeyZeit5 ;Nein =>
LD HL,TempBZeit+1
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
KeyZeit5: LD HL,GesamtBZeit ;Gesamtbetriebsstunden
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
KeyZeit6: RES 4,A ;Zeit-LED-Flag an
OR 0Fh ;Tag,Nacht,Ein,Aus-LEDs aus
LD (IX+KLED),A ;LED-Status setzen
LD A,(IX+KLED+1)
IF NewVersion
OR 0Fh ;alle LEDs aus
ELSE
OR 0Dh ;bis auf Temperatur alle LEDs aus (WARUM???)
ENDIF
LD (IX+KLED+1),A
BIT 7,(IX+KLED) ;"Setzen" an?
JR NZ,KeyZeit8 ;Nein =>
BIT 4,(IX+KLED+1) ;"Kanal 1" an?
JR NZ,KeyZeit7 ;Nein! =>
LD (IX+Uni1Flag),55h
LD HL,StrLrUNI1 ;" UNI-1"
SET 7,(IX+KLED) ;"Setzen" aus
JP SetDisplayString
KeyZeit7: BIT 5,(IX+KLED+1) ;"Kanal 2" an?
RET NZ ;Nein =>
LD (IX+Uni2Flag),55h
LD HL,StrLrUNI2 ;" UNI-2"
SET 7,(IX+KLED) ;"Setzen" aus
JP SetDisplayString
KeyZeit8: RET
;"Ein" gedrückt
KeyEin: LD HL,StrLrEIN ;"Lr-EIn"
LD B,55h ;Ein-Flag
RES 2,(IX+KLED) ;Ein-LED an
SET 3,(IX+KLED) ;Aus-LED aus
JR KeyAus1
;"Aus" gedrückt
KeyAus: LD HL,StrLrAUS ;"Lr-AUS"
LD B,AAh ;Aus-Flag
RES 3,(IX+KLED) ;Aus-LED an
SET 2,(IX+KLED) ;Ein-LED aus
KeyAus1: RES 0,(IX+Flags) ;Zahleingabe aus
BIT 5,(IX+KLED+1) ;"Kanal 2"
JP NZ,KeyAus2 ;Nein =>
BIT 2,(IX+KLED+1) ;"Leitwert"
JP NZ,KeyAus2 ;Nein =>
BIT 7,(IX+KLED) ;"Setzen" an?
JP NZ,KeyAus2 ;Nein! =>
LD (IX+Uni2Flag),AAh ;Leitwert-Regelung
LD (IX+Uni2Flag2),B ;Ein- oder Aus-Regelung setzen
SET 7,(IX+KLED) ;"Setzen"-LED aus
JP SetDisplayString
;Display löschen
KeyStern: LD HL,Display
LD B,6
KeyStern1: LD (HL),0 ;6 mal '0' ins Display (führende Nullen werden NICHT ausgegeben)
INC HL
DJNZ KeyStern1
INC HL
RES 0,(HL) ;Zahleingabe aus
INC HL
INC HL
LD (HL),FFh ;alle Punkte im Display aus
LD B,A
LD (IX+KLED+1),FFh
LD A,BFh
OR (IX+KLED)
LD (IX+KLED),A ;Bis auf manuelles Licht alle Tasten-LEDs aus
SET 0,(IX+Flags) ;Zahleingabe an
RES 2,(IX+Flags) ;PowerOn-Flag zurücksetzen
RES 3,(IX+Flags) ;keine Momentan-Werte durchschalten
IF !NewVersion
LD A,AAh
LD (LaufschriftFlag),A ;Laufschrift ausschalten
LD (LaufschriftInit),A
ENDIF
LD A,6
LD (DelayTimer),A
RES 4,(IX+Flags) ;Zahl im Display
LD A,0
LD (ErrorCode),A ;Fehlercode löschen
LD A,B
LD (C000h),A
RET
;Diese Routine wird bei Druck auf "." angesprungen
KeyPunkt: BIT 0,(IX+Flags) ;Zahleingabe an?
CALL Z,KeyStern ;Nein! => erstmal das Display löschen
SET 0,(IX+Flags) ;Zahleingabe aktivieren
LD A,(IX+DPunkt)
XOR 01h ;Dezimalpunkt toggeln
LD (IX+DPunkt),A
LD (C000h),A
RET
;pH-Taste gedrückt
KeyPh: LD (IX+KLED+1),FEh ;pH-LED an
RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED)
OR 18h ;Zeit und Aus LEDs aus
LD (IX+KLED),A
BIT 5,(IX+KLED) ;"Momentan"?
RET Z ;Ja => raus
BIT 7,(IX+KLED) ;"Setzen" an?
JR Z,KeyPh1 ;Ja! =>
JP DispSollPh ;Soll-pH-Wert darstellen
KeyPh1: LD HL,Display
IF !NewVersion
LD A,0
OR (HL)
INC HL
OR (HL)
INC HL
OR (HL)
JR NZ,KeyPh2
INC HL
LD A,(HL)
CP 1
JR NZ,KeyPh2 ;"15.0" eingegeben?
INC HL
LD A,(HL)
CP 5
JR NZ,KeyPh2 ;Nein =>
INC HL
LD A,(HL)
CP 0
JR NZ,KeyPh2
LD A,(IX+DPunkt)
CP FDh ;Dezimalpunkt
JR NZ,KeyPh2
LD A,55h
LD (LaufschriftFlag),A ;Laufschrift an
LD HL,MsgBasis
LD (LaufschriftPtr),HL ;Laufschrift-Text
RET
ENDIF
KeyPh2: CALL GetNumInput ;Eingabe holen
LD A,D ;Anzahl der Dezimalpunkte holen
CP 0
JR Z,KeyPh3
CP 1 ;0 oder 1 ist i.O.
JR Z,KeyPh4
LD A,3
JP MakeErrCode ;mehrere Dezimalpunkte bei pH-Werteingabe
KeyPh3: LD IY,InputBuf+7 ;Ptr auf die letzte Ziffer
KeyPh4: LD B,E ;Position des Dezimalpunktes (1...6)
LD A,0
INC IY
PUSH IY
KeyPh5: OR (IY-2) ;alle Ziffern _VOR_ der 1.Vorkommastelle zusammen"OR"n
DEC IY
DJNZ KeyPh5
POP IY
CP 0 ;gibt es dort Ziffern <> "0"?
JR Z,KeyPh6 ;Nein! =>
LD A,1
JP MakeErrCode ;pH-Wert zu groß!
KeyPh6: CALL ConvertInput ;pH-Wert holen
LD A,L
SUB 38 ;3.8 ist für einen pH-Wert zu klein!
JR C,KeyPh7 ;< 3.8 => Fehler
JR Z,KeyPh7 ;= 3.8 => Fehler
JR KeyPh8 ;alles ok =>
KeyPh7: LD A,2
JP MakeErrCode ;pH-Wert zu klein
KeyPh8: SLA A ;mal 2
LD B,A
LD A,(IY+1) ;2.Nachkommastelle holen
CP 3
JR C,KeyPh10 ;<0.03? => nicht aufrunden
CP 8
JR C,KeyPh9 ;<0.08? => auf 0.05 aufrunden
INC B ;>=0.08? => auf 0.10 aufrunden
KeyPh9: INC B
KeyPh10: LD (IX+SollpH),B ;als neuen pH-Sollwert merken ((pH-Wert*10-38)*2)
CALL CalcSollChecksum ;Prüfsumme über die Sollwerte errechnen
LD (SollChecksum),DE ;und merken
SET 7,(IX+KLED) ;"Setzen" aus
LD (C000h),A
DispSollPh: LD A,(IX+SollpH) ;neuen pH-Wert holen
;pH-Wert darstellen
DispPh: BIT 0,A ;Bit 0 = 2.Nachkommastelle
JR Z,DispPh1
LD B,5 ;gesetzt = 0.05
JR DispPh2
DispPh1: LD B,0 ;gelöscht = 0.00
DispPh2: LD (IX+Display+2),B
SRL A ;(pH-Wert / 2) + 38
ADD A,38
LD E,A
LD D,0
PUSH DE
POP IY ;Zahl nach IY
CALL MakeBCD
LD HL,BCDZahl ;Ptr auf die BCD-Zahl
LD A,0
RRD (HL) ;unteres Nibble ab HL nach A holen
LD (IX+Display+1),A ;2.Stelle
RRD (HL) ;oberes Nibble ab HL nach A holen
LD (IX+Display),A ;1.Stelle
LD (IX+Display+3),1Fh ;Leerzeichen
LD (IX+Display+4),12h ;"P"
LD (IX+Display+5),10h ;"H"
LD (IX+DPunkt),DFh ;Dezimalpunkt nach der 1.Stelle
LD (C000h),A
RET
;"Setzen" gedrückt
KeySetzen: RES 0,(IX+Flags) ;Zahleingabe aus
IN A,(C) ;Sperre gesetzt?
BIT 4,A ;Ja! =>
JR Z,KeySetzen1
BIT 4,(IX+Flags) ;Zahl im Display?
CALL NZ,KeyStern ;Nein! =>
LD A,(IX+KLED)
XOR 80h ;Setzen-toggeln
OR 3Fh ;bis auf "Manuell" alle LEDs ausschalten
LD (IX+KLED),A
LD (IX+KLED+1),FFh
LD (C000h),A
RET
KeySetzen1: LD A,99h ;Programmiersperre gesetzt
JP MakeErrCode
;"Momentan" gedrückt
KeyMomentan: RES 0,(IX+Flags) ;Zahleingabe aus
BIT 5,(IX+KLED) ;"Momentan" bereits an?
JR NZ,KeyMomentan1 ;Nein =>
SET 3,(IX+Flags) ;Momentane Werte durchschalten
IF NewVersion
LD A,0
LD (DelayTimer),A ;sofortige Ausgabe der Werte erzwingen
DEC A
LD (MomentanSek),A
ENDIF
JR KeyMomentan2
KeyMomentan1: RES 3,(IX+Flags) ;Momentane Werte nicht mehr durchschalten
KeyMomentan2: RES 5,(IX+KLED) ;Momentan-LED an
LD A,(IX+KLED)
OR 0Fh ;Tag, Nacht, Ein, Aus LEDs ausschalten
LD (IX+KLED),A
LD (IX+KLED+1),FFh ;rechte LEDs ausschalten
BIT 7,(IX+KLED) ;"Setzen" an?
LD (C000h),A
RET NZ ;Nein =>
BIT 4,(IX+KLED) ;"Zeit" an?
JR Z,KeyMomentan4 ;Ja! =>
IF NewVersion
LD A,0
LD B,4
LD HL,Display ;die ersten 4 Ziffern müssen stets = 0 sein
KeyMomentan6: OR (HL)
INC HL
DJNZ KeyMomentan6
JR NZ,KeyMomentan7 ;wenn nicht => Fehler
LD IY,Display+5 ;Ptr auf die letzte Stelle vom Display
CALL ConvertInput ;Zahl nach HL holen
LD A,L
LD HL,MomentanZeit
LD (HL),A ;aktuelle Schaltzeit merken
SET 7,(IX+KLED) ;Setzen-LED aus
ENDIF
KeyMomentan3: SET 5,(IX+KLED) ;Momentan-LED aus
RET
IF NewVersion
KeyMomentan7: LD A,20h
JP MakeErrCode ;Eingabe falsch!
ENDIF
KeyMomentan4: LD BC,0A00h ;2560 Schleifendurchläufe
KeyMomentan5: HALT
LD A,(KeyboardMatrix+6)
BIT 2,A ;Manuell immer noch gedrückt?
JR NZ,KeyMomentan3 ;Nein => Zeit nicht neu setzen
LD (C000h),A
HALT
DEC BC ;Zähler runterzählen
LD A,B ;0 erreicht?
OR C
JR NZ,KeyMomentan5 ;Nein => weiter warten
SET 5,(IX+KLED) ;Momentan-LED aus
JP SetSystemTime
;"Temperatur"-Taste gedrückt
KeyTemperatur: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED+1)
RES 1,A ;Temperatur an
OR FDh ;andere LEDs aus
LD (IX+KLED+1),A
LD A,(IX+KLED)
OR 1Fh ;außer Momentan, Manuell und Setzen alles aus
LD (IX+KLED),A
LD (C000h),A
RET
;"Kanal 1" gedrückt
KeyKanal1: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED)
OR 1Fh ;Tag,Nacht,Ein,Aus,Zeit im linken Bereich aus
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR FFh ;alle LEDs im rechten Bereich aus
RES 4,A ;und "Kanal 1"-LED an
LD (IX+KLED+1),A
BIT 5,(IX+KLED) ;"Momentan" an?
RET NZ ;Nein => raus
LD A,(IX+Uni1Flag) ;Zustand von Kanal 1
CP 55h
JR Z,KeyKanal12 ;=> Universaltimer
CP AAh
JR Z,KeyKanal11 ;=> Redox-Regler
LD HL,Str6Minus ;"------"
JP SetDisplayString
KeyKanal11: LD HL,StrrErE ;" rE-rE"
JP SetDisplayString
KeyKanal12: LD HL,StrLrUNI1 ;" UNI-1"
JP SetDisplayString
;"Kanal 2" gedrückt
KeyKanal2: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED)
OR 1Fh ;Tag,Nacht,Ein,Aus,Zeit im linken Bereich aus
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR FFh ;alle LEDs im rechten Bereich aus
RES 5,A ;und "Kanal 2"-LED an
LD (IX+KLED+1),A
BIT 5,(IX+KLED) ;"Momentan" an?
RET NZ ;Nein => raus
LD A,(IX+Uni2Flag) ;Zustand von Kanal 2
CP 55h
JR Z,KeyKanal24 ;=> Universaltimer
CP AAh
JR Z,KeyKanal21 ;=> Leitwert-Regler
LD HL,Str6Minus ;"------"
JP SetDisplayString
KeyKanal21: LD A,(IX+Uni2Flag2) ;Ein- oder Aus-Regelung?
CP 55h
JR Z,KeyKanal23 ;=> Ein-Regelung
CP AAh
JR Z,KeyKanal22 ;=> Aus-Regelung
LD HL,Str6Minus ;"------"
JP SetDisplayString
KeyKanal22: LD HL,StrLrAUS ;"Lr-AUS"
JP SetDisplayString
KeyKanal23: LD HL,StrLrEIN ;"Lr-EIN"
JP SetDisplayString
KeyKanal24: LD HL,StrLrUNI2 ;" UNI-2"
JP SetDisplayString
;"CO2" gedrückt
KeyCO2: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED+1)
RES 7,A ;CO2-LED an
OR 7Fh ;alle LEDs aus
LD (IX+KLED+1),A
LD A,(IX+KLED)
OR 3Fh ;bis auf "Manuell" und "Setzen" alle LEDs aus
LD (IX+KLED),A
LD (C000h),A
RET
;"Licht" gedrückt
KeyLicht: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED+1)
RES 6,A ;Licht-LED an
OR BFh ;alle LEDs aus
LD (IX+KLED+1),A
LD A,(IX+KLED)
OR 3Fh ;bis auf "Manuell" und "Setzen" alle LEDs aus
LD (IX+KLED),A
LD (C000h),A
RET
;"Tag" gedrückt
KeyTag: LD HL,TagZeit ;Ptr auf Tagdaten
RES 0,(IX+KLED) ;Tag an
SET 1,(IX+KLED) ;Nacht aus
JR KeyNacht1
;"Nacht" gedrückt
KeyNacht: LD HL,NachtZeit ;Ptr auf Nachtdaten
RES 1,(IX+KLED) ;Nacht an
SET 0,(IX+KLED) ;Tag aus
KeyNacht1: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED)
OR 2Ch ;Ein, Aus und Momentan aus
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR FDh ;bis auf "Temperatur" alles aus
LD (IX+KLED+1),A
BIT 7,(IX+KLED) ;"Setzen" an?
JR Z,KeyNacht2 ;Ja! =>
BIT 4,(IX+KLED) ;"Zeit" an?
JP Z,PrintTime ;Ja! =>
BIT 1,(IX+KLED+1) ;"Temperatur" an?
JP Z,PrintSollTemp ;°C ausgeben
JR KeyNacht3
KeyNacht2: BIT 4,(IX+KLED) ;"Zeit" an?
JP Z,GetDispTime ;Ja! => Zeit für Tag oder Nacht setzen
BIT 1,(IX+KLED+1) ;"Temperatur" an?
JP Z,SetSollTemp ;Temperatur für Tag oder Nacht setzen =>
SET 7,(IX+KLED) ;"Setzen" aus
KeyNacht3: SET 1,(IX+KLED) ;Nacht aus
SET 0,(IX+KLED) ;Tag aus
LD (C000h),A
RET
;"Manuell" gedrückt
KeyManuell: RES 0,(IX+Flags) ;Zahleingabe aus
LD A,(IX+KLED)
BIT 7,A ;"Setzen" an?
JR Z,KeyManuell2 ;Ja! =>
LD BC,3
LD DE,ManuellEinZeit
LD HL,AktTime ;Uhrzeit retten
LDIR
LD HL,ManuellZeit
BIT 4,A ;"Zeit" an?
JR NZ,KeyManuell1 ;Nein =>
BIT 5,A ;"Momentan" an?
JP NZ,PrintTime ;Nein! (Zeit an, Momentan aus) => Ausschaltzeit ausgeben
KeyManuell1: XOR 40h
LD (IX+KLED),A ;Manuell-Flag toggeln
RET
KeyManuell2: LD HL,ManuellZeit
IF !NewVersion
CALL GetDispTime ;Zeit für "Manuell"-Taste setzen
LD A,(IX+Display)
CP 0Fh ;"FEHL"er...
RET Z ;Ja => raus
RES 4,(IX+KLED) ;Zeit-LED an
LD B,6
KeyManuell3: LD HL,Display+5
LD A,(HL)
CP 1 ;"11.11.11" eingegeben?
RET NZ ;Nein =>
INC HL
DJNZ KeyManuell3
LD A,55h
LD (LaufschriftFlag),A ;Laufschrift an
LD HL,MsgPause
LD (LaufschriftPtr),HL ;Laufschrift-Text
RET
ENDIF
;Uhrzeit nach HL aus dem Display setzen
GetDispTime: LD DE,TempTime
LD A,(IX+DPunkt) ;Dezimalpunkte holen
CP FBh ;hh.mm
JR Z,GetDispTime2
CP EBh ;hh.mm.ss
JR Z,GetDispTime1
LD A,7
JP MakeErrCode ;Dezimalpunkte an falscher Position
GetDispTime1: LD B,2 ;zwei Dezimalpunkte (noch zwei Zahlen holen)
LD C,4 ;zuerst: Fehler bei den Sekunden
JR GetDispTime4
GetDispTime2: LD A,0
OR (IX+Display+1) ;zwei Ziffern (ganz links) eingegeben?
OR (IX+Display)
JR Z,GetDispTime3 ;Nein =>
LD A,6
JP MakeErrCode ;mehr als 23h eingegeben
GetDispTime3: LD (DE),A ;ohne Sekunden: 0 Sekunden setzen
INC DE
LD B,1 ;ein Dezimalpunkt (noch eine Zahl holen)
LD C,5 ;zuerst: Fehler bei den Minuten
GetDispTime4: LD IY,Display+5 ;Ptr auf die letzte Ziffer im Display
GetDispTime5: LD A,(IY-1) ;Ziffer davor holen
ADD A,A
ADD A,A ;*16
ADD A,A
ADD A,A
OR (IY+0) ;und die Ziffer dazu (=> BCD-Zahl)
CP 5Ah ;5A = 50+10 = 60!
JR C,GetDispTime6 ;kleiner? => ja
SET 7,C ;Fehler!
GetDispTime6: LD (DE),A ;Zahl merken
INC DE
DEC IY ;zwei Ziffern nach vorne
DEC IY
INC C ;Fehlernummer hochsetzen (Sekunden => Minuten)
DJNZ GetDispTime5 ;alle Dezimalpunkte durch?
LD A,(IY-1)
ADD A,A
ADD A,A
ADD A,A ;Stunden in BCD wandeln
ADD A,A
OR (IY+0)
CP 24h ;größer als 24h?
JR C,GetDispTime7 ;Nein =>
SET 7,C ;Fehler!
GetDispTime7: LD (DE),A ;Stunden merken
BIT 7,C ;ein Fehler aufgetreten?
JR Z,GetDispTime8 ;Nein =>
RES 7,C ;Flag löschen
LD A,C
JP MakeErrCode ;Fehler melden
GetDispTime8: EX DE,HL
DEC HL
DEC HL
LD BC,3
LDIR ;Uhrzeit nach HL übertragen
SET 7,(IX+KLED) ;"Setzen" aus
LD (C000h),A
RET
; 3 Bytes ab HL als 6 stellige Uhrzeit ausgeben
PrintTime: LD DE,Display+5 ;Ptr auf die letzte Stelle vom Display
LD B,3
PUSH HL
INC HL
INC HL
LD A,'0'
CP (HL) ;Stunden < '0'?
POP HL
JR NC,PrintTime1 ;Nein =>
LD HL,Str6Minus ;"------" (Uhrzeit nicht gesetzt)
JP SetDisplayString
PrintTime1: LD A,(HL) ;Byte holen
AND 0Fh
LD (DE),A ;unteres Nibble nach (DE)
DEC DE
LD A,(HL)
RRCA
RRCA
RRCA
RRCA
AND 0Fh
LD (DE),A ;oberes Nibble nach (DE-1)
DEC DE
INC HL
DJNZ PrintTime1
LD (IX+DPunkt),EBh ;Dezimalpunkte nach der 2. und der 4.Ziffer
LD (C000h),A
RET
;Tag-/Nachttemperatur setzen
SetSollTemp: PUSH HL
CALL GetNumInput
POP HL
LD A,D ;Anzahl der Dezimalpunkte
CP 0
JR Z,SetSollTemp1
CP 1
JR Z,SetSollTemp2
LD A,10h
JP MakeErrCode ;Dezimalpunkte bei der Temperatur...
SetSollTemp1: LD IY,InputBuf+7
IF !NewVersion
LD A,0
CP (IY+0)
JR NZ,SetSollTemp2
CP (IY-1) ;100° C
JR NZ,SetSollTemp2
LD A,1
CP (IY-2)
JR NZ,SetSollTemp2
LD A,55h
LD (LaufschriftFlag),A ;Laufschrift an
LD HL,MsgHeiss
LD (LaufschriftPtr),HL ;Laufschrift-Text
RET
ENDIF
SetSollTemp2: LD B,E
LD A,0
INC IY
PUSH IY
SetSollTemp3: OR (IY-3)
DEC IY
DJNZ SetSollTemp3
POP IY
CP 0
JR Z,SetSollTemp4
LD A,08h
JP MakeErrCode ;eingegeben Temp. zu groß
SetSollTemp4: PUSH HL
CALL ConvertInput
LD A,(IY+1)
CP 5
JR C,SetSollTemp5 ;<0.05°? =>
INC HL ;aufrunden (+ 0.1°)
SetSollTemp5: LD DE,100
XOR A
SBC HL,DE
JR C,SetSollTemp8 ;<10.0° =>
JR Z,SetSollTemp8 ;=10.0° =>
LD A,00h
CP H
JR NZ,SetSollTemp6 ;>(10° + 25.5°) =>
LD A,FFh
CP L
JR NZ,SetSollTemp7 ;<>(10° + 25.5°) =>
SetSollTemp6: LD A,8
POP HL
JP MakeErrCode ;eing. Temp zu groß
SetSollTemp7: LD A,L
POP HL
INC HL
INC HL
INC HL
LD (HL),A ;Temperatur (10.1°...35.4°) setzen
CALL CalcSollChecksum ;Prüfsumme über die Sollwerte errechnen
LD (SollChecksum),DE ;und merken
SET 7,(IX+KLED) ;"Setzen" aus
LD L,A
LD (C000h),A
JR DispTemp
SetSollTemp8: LD A,09h
POP HL
JP MakeErrCode ;eing. Temp zu tief
;Soll-Tag-/Nachttemperatur ausgeben
PrintSollTemp: INC HL
INC HL
INC HL
LD L,(HL) ;Soll-Temperatur auslesen
;Temperatur-Wert darstellen
DispTemp: LD H,0
LD DE,100
ADD HL,DE ;+10.0°
PUSH HL
POP IY
CALL MakeBCD
LD HL,(BCDZahl)
LD DE,Display
LD B,3 ;3 Ziffern
DispTemp1: LD A,H
AND 0Fh
LD (DE),A
ADD HL,HL
ADD HL,HL ;HL *= 16
ADD HL,HL
ADD HL,HL
INC DE
DJNZ DispTemp1
EX DE,HL
LD (HL),1Fh ;Space
INC HL
LD (HL),18h ;°
INC HL
LD (HL),0Ch ;C
LD (IX+DPunkt),EFh ;Punkt in der 2.Ziffer an
LD (C000h),A
RET
;Meßwert C (0...3) vom Hauptgerät empfangen (Wert nach A)
GetMesswert: LD HL,E000h
LD A,(IX+Steckdosen) ;Steckdosen-Bits
AND 5Fh ;Bit 0...4 übernehmen, Bit 5&7 löschen
OR 40h ;Bit 6 setzen
SET 6,(IX+Flags)
HALT
LD (HL),A ;567:010 (Bit 7 löschen = Übertragung init)
CALL Delay
LD E,A
SET 5,E
LD (HL),E ;567:110 (Bit 5 toggeln: Übertragung start)
CALL Delay
;Meßwert-Nummer (2 Bits) senden
LD D,A
LD B,2 ;2 Bits (für 4 Meßwerte) senden
LD (HL),D ;567:010
CALL Delay
LD (HL),E ;567:110 (1-Bit senden = Startbit)
CALL Delay
LD (HL),D ;567:010
GetMesswert1: SRL C
JR C,GetMesswert2 ;gesetzt =>
RES 6,D ;Bit 6 löschen, wenn Carry gelöscht
RES 6,E
LD (HL),D ;567:000
CALL Delay
LD (HL),E ;567:100 (0-Bit senden)
CALL Delay
LD (HL),D ;567:000
DJNZ GetMesswert1 ;alle 2 Bits übertragen? Nein =>
JR GetMesswert3
GetMesswert2: SET 6,D ;Bit 6 setzen, wenn Carry gesetzt
SET 6,E
LD (HL),D ;567:010
CALL Delay
LD (HL),E ;567:110 (1-Bit senden)
CALL Delay
LD (HL),D ;567:010
DJNZ GetMesswert1 ;alle 2 Bits übertragen? Nein =>
GetMesswert3: LD B,8 ;8 Bits empfangen
LD (HL),E ;567:1?0 (Bit erwarten)
CALL Delay
IN C,(C) ;Bit auslesen
BIT 5,C ;0-Startbit?
JR Z,GetMesswert4 ;Ja =>
SET 7,E
SET 6,E
LD (IX+Steckdosen),E
LD (HL),E ;567:1?1 (Übertragung beendet)
SCF
CCF ;Carry = NOT 1 = 0 (Übertragung mit Fehler)
RET
GetMesswert4: LD (HL),D ;567:0?0 (Bit empfangen)
CALL Delay
LD A,0 ;Bytewert = 0
LD (HL),E ;567:1?0 (Bit erwarten)
GetMesswert5: CALL Delay
ADD A,A ;Bytewert * 2
IN C,(C)
BIT 5,C ;Bit abfragen
LD (HL),D ;567:0?0 (Bit empfangen)
CALL Delay
JR Z,GetMesswert6 ;Bit gelöscht =>
SET 0,A ;unterstes Bit setzen
GetMesswert6: LD (HL),E ;567:1?0 (Bit erwarten)
CALL Delay
DJNZ GetMesswert5 ;alle 8 Bits empfangen? Nein =>
SET 7,E
SET 6,E
LD (IX+Steckdosen),E
LD (HL),E ;567:111 (Übertragung beendet)
CALL Delay
RES 6,(IX+Flags)
SCF ;Carry = 1 (Übertragung ok)
RET
;ein paar Takte verzögern
Delay: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RET
;Potential in L ausgeben
DispRedox: LD (IX+DPunkt),FFh ;Dezimalpunkte aus
LD (IX+Display+5),19h ;o
LD (IX+Display+4),12h ;P
LD (IX+Display+3),1Fh ;Space
LD H,0
ADD HL,HL
PUSH HL
POP IY
CALL MakeBCD
LD HL,(BCDZahl)
LD DE,Display
LD B,3
DispRedox1: LD A,H
AND 0Fh
LD (DE),A
ADD HL,HL
ADD HL,HL ;HL *= 16
ADD HL,HL
ADD HL,HL
INC DE
DJNZ DispRedox1
LD (C000h),A
RET
;Systemzeit (aus dem Display) in dem RTC setzen
SetSystemTime: LD HL,AktTime
CALL GetDispTime ;Uhrzeit aus dem Display lesen
LD A,(IX+Display)
CP 0Fh ;"F"ehler?
RET Z ;Ja => raus
LD HL,AktTime
CALL PrintTime ;Uhrzeit formatiert ausgeben
LD HL,Display
SET 3,(HL) ;Bit 3 in der 1.Stundenziffer setzen (24h Format)
LD B,6 ;6 Register setzen
LD C,5
LD IY,4000h ;Adresse vom RTC
HALT
SetSystemTime1: LD (IY+1),C ;Register auswählen
LD A,(HL) ;Ziffer auslesen
LD (IY+2),A ;und ins RTC-Register schreiben
INC HL
DEC C ;Register - 1
DJNZ SetSystemTime1
RES 5,(IX+KLED) ;"Momentan"-LED ausschalten
LD (C000h),A
RET
;Universaltimer-Verwaltung
UniTimer: LD B,10 ;maximal 10 Zeiten
UniTimer1: PUSH HL
INC HL
INC HL
BIT 7,(HL) ;Ende der Liste? (Einschaltzeit)
POP HL
JR Z,UniTimer2 ;Nein =>
SCF ;Ja, Carry setzen und raus
RET
UniTimer2: PUSH DE
INC DE
INC DE
LD A,(DE) ;Ende der Liste? (Ausschaltzeit)
POP DE
BIT 7,A
JR Z,UniTimer3 ;Nein =>
SCF ;Ja, Carry setzen und raus
RET
UniTimer3: PUSH BC
PUSH DE
PUSH HL
CALL InTimeRange ;im Einschaltbereich?
POP HL
POP DE
POP BC
RET NC ;Ja! => raus
INC HL
INC HL ;nächste Einschaltzeit
INC HL
INC DE
INC DE ;nächste Ausschaltzeit
INC DE
DJNZ UniTimer1 ;alle Zeiten durch?
LD (C000h),A
RET
;HL: Einschaltzeit
;DE: Ausschaltzeit
;Carry = 0, wenn im Zeitraum
InTimeRange: PUSH DE
PUSH HL
CALL CompareTimes ;sind die beiden Zeiten gleich?
POP HL
POP DE
RET Z ;Ja => raus
JR C,InTimeRange1 ;Ausschaltzeit < Einschaltzeit? => Zeiten und Logik drehen
PUSH DE
LD DE,AktTime
CALL CompareTimes ;HL mit der aktuellen Uhrzeit vergleichen
POP DE
RET Z ;Einschaltzeit = aktuelle Zeit? => raus
RET C ;Einschaltzeit > aktuelle Zeit? => raus
LD HL,AktTime
CALL CompareTimes
RET C ;Ausschaltzeit > aktuelle Zeit? => raus
RET NZ ;Ausschaltzeit <> aktuelle Zeit? => raus
SCF ;Carry = 1 (außerhalb)
RET
InTimeRange1: EX DE,HL
PUSH DE
LD DE,AktTime
CALL CompareTimes
POP DE
CCF ;Carry = NOT Carry
RET NC
JR NZ,InTimeRange2
SCF ;Carry = 1 (außerhalb)
RET
InTimeRange2: LD HL,AktTime
CALL CompareTimes
RET Z
CCF ;Carry = NOT Carry
RET
;Zeit DE und HL vergleichen, Z = 1, wenn gleich
CompareTimes: LD BC,0300h ;3 Bytes (Sekunden,Minuten,Stunden) vergleichen
XOR A
CompareTimes1: LD A,(DE)
SBC A,(HL)
JR Z,CompareTimes2
SET 0,C ;Flag setzen, wenn ungleich!
CompareTimes2: INC HL
INC DE
DJNZ CompareTimes1
LD (C000h),A
BIT 0,C ;Z = 1, wenn gleich
RET
;Leitwert-Wert darstellen
DispLeitw: LD H,0
BIT 5,(IX+KLED) ;"Momentan" an?
JR NZ,DispLeitw4 ;Nein =>
LD A,(IX+IstTemp) ;Ist-Temp-Wert
CP FFh
JR Z,DispLeitw6 ;Temperatur außerhalb des Meßbereiches?
CP 00h
JR Z,DispLeitw6 ;Ja =>
LD A,(IX+LeitwertKomp) ;kompensierter Leitwert
LD L,A
CP FFh ;ungültig?
JR NZ,DispLeitw2 ;Nein =>
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DispLeitw1
LD HL,Str6Space ;" "
JP SetDisplayString
DispLeitw1: LD HL,StrFEHL16 ;"FEHL16"
JP SetDisplayString
DispLeitw2: CP 00h ;Bereich unterschritten?
JR NZ,DispLeitw4 ;Nein =>
BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DispLeitw3
LD HL,Str6Space ;" "
JP SetDisplayString
DispLeitw3: LD HL,StrFEHL15 ;"FEHL15"
JP SetDisplayString
DispLeitw4: IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
JR Z,DispLeitw5 ;Meerwasser =>
LD DE,1505h ;"µS"
LD (IX+Display+3),00h ;"0"
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
JR DispLeitw9
DispLeitw5: LD DE,350 ;35.0mS Vorgabe (Minumum bei Meerwasser-Leitwert)
ADD HL,DE
LD DE,1705h ;"nS"
LD (IX+Display+3),1Fh ;Space
LD (IX+DPunkt),EFh
JR DispLeitw9
DispLeitw6: LD L,(IX+IstLeitw) ;Ist-Leitwert (nicht kompensiert)
IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
JR Z,DispLeitw7 ;Meerwasser =>
LD DE,1505h ;"µS"
LD (IX+Display+3),00h ;"0"
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
JR DispLeitw8
DispLeitw7: LD DE,350 ;35.0mS Vorgabe (Minumum bei Meerwasser-Leitwert)
ADD HL,DE
LD DE,1705h ;"nS"
LD (IX+Display+3),1Fh ;Space
LD (IX+DPunkt),EFh ;Punkt nach der 2.Ziffer
DispLeitw8: BIT 0,(IX+Counter+1) ;Blink-Timer gesetzt?
JR Z,DispLeitw9
LD DE,1F1Fh ;" "
DispLeitw9: LD (IX+Display+5),E ;Einheit setzen
LD (IX+Display+4),D
PUSH HL
POP IY
CALL MakeBCD ;Leitwert nach BCD wandeln
LD HL,(BCDZahl) ;BCD-Zahl holen
LD DE,Display
LD B,3 ;3 Ziffern ins Display
DispLeitw10: LD A,H
AND 0Fh
LD (DE),A ;Ziffer ins Display
ADD HL,HL
ADD HL,HL ;HL * 16
ADD HL,HL
ADD HL,HL
INC DE ;eine Stelle weiter
DJNZ DispLeitw10 ;alle drei Ziffern durch? Nein =>
LD (C000h),A
RET
;Fehlermeldung A für das Display zusammensetzen
MakeErrCode: LD HL,Display
LD (HL),0Fh ;"F"
INC HL
LD (HL),0Eh ;"E"
INC HL
LD (HL),10h ;"H"
INC HL
LD (HL),11h ;"L"
LD (IX+DPunkt),FBh ;FBh (Bit 2 gelöscht): Punkt in der 4.Stelle setzen?!?
LD B,A
AND 0Fh
LD (IX+Display+5),A ;Fehlercode (untere Ziffer)
LD A,B
RRCA
RRCA
RRCA
RRCA
AND 0Fh
JR NZ,MakeErrCode1 ;zweistellige Ziffer? Ja =>
LD A,1Fh ;Nein = Feld frei
MakeErrCode1: LD (IX+Display+4),A ;erste Ziffer
SET 4,(IX+Flags) ;keine Zahl im Display
LD (C000h),A
RET
;Eingabe (drei Ziffern) in eine binäre Zahl in HL wandeln
ConvertInput: LD HL,0 ;Zahlenwert
LD A,(IY-2) ;1.Ziffer holen
CP 0 ;= "0"?
JR Z,ConvertInput2 ;Ja! =>
LD B,A
LD DE,100
ConvertInput1: ADD HL,DE ;100 * Wert der 1.Ziffer addieren
DJNZ ConvertInput1
ConvertInput2: LD A,(IY-1) ;2.Ziffer holen
CP 0 ;= "0"?
JR Z,ConvertInput4 ;Ja! =>
LD B,A
LD DE,10
ConvertInput3: ADD HL,DE ;10 * Wert der 2.Ziffer addieren
DJNZ ConvertInput3
ConvertInput4: LD E,(IY+0) ;3.Ziffer
LD D,0
ADD HL,DE ;zum Wert addieren
LD (C000h),A
RET
;binäre Zahl in IY nach BCDZahl in gepacktem BCD wandeln
MakeBCD: ADD IY,IY ;Zahl * 4
ADD IY,IY
LD B,14 ;14 Bits (2 Bits sind durch * 4 weg)
LD HL,BinDezTableEnd-1 ;Multiplikationstabelle
LD DE,BCDZahl
LD (IX+BCDZahl),0
LD (IX+BCDZahl+1),0
MakeBCD1: ADD IY,IY ;Zahl * 2
JR C,MakeBCD2 ;Überlauf? => Ja!
DEC HL ;eine Stelle in der Mult-Tabelle zurück
DEC HL
DJNZ MakeBCD1 ;alle Stellen durch? Nein =>
RET
MakeBCD2: XOR A ;A = 0
LD A,(DE)
ADC A,(HL) ;untere Bytes addieren
DAA ;in gepacktes BCD wandeln
LD (DE),A ;und zurückschreiben
DEC HL
INC DE
LD A,(DE) ;obere Bytes addieren
ADC A,(HL)
DAA ;in gepacktes BCD wandeln
LD (DE),A ;und zurückschreiben
DEC HL
DEC DE
LD (C000h),A
DJNZ MakeBCD1 ;zur nächsten Stelle
RET
KeyAus2: BIT 4,(IX+KLED+1) ;"Kanal 1"
JP Z,KeyAus15 ;Ja =>
BIT 5,(IX+KLED+1) ;"Kanal 2"
JP Z,KeyAus16 ;Ja =>
BIT 6,(IX+KLED+1) ;"Licht"
JR NZ,KeyAus4 ;Nein =>
BIT 2,(IX+KLED) ;"Ein"
JR NZ,KeyAus3 ;Nein =>
BIT 7,(IX+KLED) ;"Setzen" an?
LD HL,LichtEin
JP Z,GetDispTime ;Ja! =>
JP PrintTime
KeyAus3: BIT 7,(IX+KLED) ;"Setzen" an?
LD HL,LichtAus
JP Z,GetDispTime ;Ja! =>
JP PrintTime
KeyAus4: BIT 7,(IX+KLED+1) ;"CO2"
JR NZ,KeyAus6
BIT 2,(IX+KLED) ;"Ein"
JR NZ,KeyAus5
BIT 7,(IX+KLED) ;"Setzen" an?
LD HL,CO2Ein
JP Z,GetDispTime ;Ja! =>
JP PrintTime
KeyAus5: BIT 7,(IX+KLED) ;"Setzen" an?
LD HL,CO2Aus
JP Z,GetDispTime ;Ja! =>
JP PrintTime
KeyAus6: BIT 4,(IX+KLED) ;"Zeit"
JR Z,KeyAus7 ;Ja =>
LD A,(IX+KLED)
OR 0Ch ;Ein und Aus LEDs ausschalten
LD (IX+KLED),A
RET
KeyAus7: BIT 7,(IX+KLED) ;"Setzen" an?
JR Z,KeyAus11 ;Ja! =>
LD HL,Display
LD B,6
KeyAus8: LD (HL),0 ;Display löschen
INC HL
DJNZ KeyAus8
LD (IX+DPunkt),FEh ;Dezimalpunkt in der 6.Ziffer an
LD A,(IX+AktSchaltzeit) ;aktuelle Schaltzeit
AND 0Fh
INC A
CP 10
JR Z,KeyAus9
LD (IX+Display+5),A ;1...9
JR KeyAus10
KeyAus9: LD (IX+Display+4),1 ;'10'
KeyAus10: LD (C000h),A
RET
KeyAus11: LD A,0
LD B,4
LD HL,Display ;die ersten 4 Ziffern müssen stets = 0 sein
KeyAus12: OR (HL)
INC HL
DJNZ KeyAus12
JR NZ,KeyAus13 ;wenn nicht => Fehler
LD IY,Display+5 ;Ptr auf die letzte Stelle vom Display
CALL ConvertInput ;Zahl nach HL holen
LD A,L
CP 0
JR Z,KeyAus13 ;Schaltzeiten zwischen 1 und 10
CP 11
JR NC,KeyAus13
DEC A
LD (IX+AktSchaltzeit),A ;aktuelle Schaltzeit merken
SET 7,(IX+KLED) ;"Setzen" aus
LD (C000h),A
RET
KeyAus13: LD A,19h
JP MakeErrCode ;ill. Nummer für die Schaltzeiten
IF !NewVersion
KeyAus14: LD A,20h
JP MakeErrCode ;???
ENDIF
KeyAus15: LD HL,Kanal1Uni ;Kanal 1 Schaltzeiten
JR KeyAus17
KeyAus16: LD HL,Kanal2Uni ;Kanal 2 Schaltzeiten
KeyAus17: BIT 2,(IX+KLED) ;"Ein" gedrückt?
JR Z,KeyAus18 ;Ja! =>
LD DE,30
ADD HL,DE ;Ausschaltzeiten
KeyAus18: LD DE,3
LD A,(IX+AktSchaltzeit) ;aktuelle Schaltzeit holen
CP 0
JR Z,KeyAus21 ;Schaltzeit gültig?
CP 10 ;Ja =>
JR C,KeyAus19
LD A,0
LD (IX+AktSchaltzeit),A ;Schaltzeit löschen
JR KeyAus21
KeyAus19: LD B,A
KeyAus20: ADD HL,DE ;je 3 Bytes pro Schaltzeit
DJNZ KeyAus20
KeyAus21: BIT 7,(IX+KLED) ;"Setzen" an?
JP NZ,PrintTime ;Nein! =>
LD A,(IX+Display)
OR (IX+Display+1)
OR (IX+Display+2)
OR (IX+Display+3) ;0 als Uhrzeit eingegeben?
OR (IX+Display+4)
OR (IX+Display+5)
JR Z,KeyAus22 ;Ja =>
JP GetDispTime ;Schaltzeit setzen
KeyAus22: LD A,(IX+DPunkt) ;Dezimalpunkte?
CP FFh
JP NZ,GetDispTime ;Ja =>
INC HL
INC HL
SET 7,(HL) ;Alarmzeit ungültig machen
LD DE,30
BIT 2,(IX+KLED) ;"Ein"?
JR Z,KeyAus23 ;Ja =>
XOR A
SBC HL,DE ;Ptr auf Einschaltzeit
JR KeyAus24
KeyAus23: ADD HL,DE ;Ptr auf Ausschaltzeit
KeyAus24: SET 7,(HL) ;entsprechende Zeit ebenfalls ausschalten
SET 7,(IX+KLED) ;"Setzen" aus
LD HL,Str6Minus ;"------"
JP SetDisplayString
;"Redox"-Taste gedrückt
KeyRedox: RES 0,(IX+Flags) ;Zahleingabe aus
BIT 5,(IX+KLED) ;"Momentan"?
JR NZ,KeyRedox1 ;Nein =>
LD A,(IX+KLED)
OR 9Fh ;Mometan und Manuell an lassen (Rest aus)
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR F7h ;LEDs bis auf Redox ausschalten
LD (IX+KLED+1),A
RES 3,(IX+KLED+1) ;Redox anschalten
RET
KeyRedox1: BIT 7,(IX+KLED) ;"Setzen" an?
JR Z,KeyRedox2 ;Ja! =>
LD A,(IX+KLED)
OR BFh ;bis auf Manuell alles ausschalten
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR F7h ;bis auf Redox alles ausschalten
LD (IX+KLED+1),A
RES 3,(IX+KLED+1) ;Redox anschalten
LD L,(IX+SollRedox) ;Soll-Redoxwert
JP DispRedox ;Potential anzeigen
KeyRedox2: RES 3,(IX+KLED+1) ;Redox anschalten
BIT 4,(IX+KLED+1) ;"Kanal 1" an
JR NZ,KeyRedox3 ;Nein =>
LD (IX+Uni1Flag),AAh ;Kanal 1 auf Redox-Regelung schalten
SET 7,(IX+KLED) ;"Setzen" aus
LD HL,StrrErE ;" rE-rE"
JP SetDisplayString
KeyRedox3: CALL GetNumInput ;Eingabe holen
LD A,D
CP 0
JR Z,KeyRedox4 ;0 oder 1 Dezimalpunkt in der Eingabe
CP 1
JR Z,KeyRedox5
LD A,23h
JP MakeErrCode ;mehrere Dezimalpunkte bei Redox-Eingabe
KeyRedox4: LD IY,InputBuf+7
LD E,5
KeyRedox5: LD B,E
DEC B
JR Z,KeyRedox7
LD B,1
LD A,0
PUSH IY
KeyRedox6: OR (IY-3) ;Ziffern vor der erwarteten 1.Ziffer zusammen'OR'n
DEC IY
DJNZ KeyRedox6
POP IY
CP 0
JR Z,KeyRedox7
LD A,21h
JP MakeErrCode ;zu großer Redox-Wert eingegeben
KeyRedox7: CALL ConvertInput
BIT 0,L ;Redox-Wert gerade?
JR Z,KeyRedox8 ;Ja =>
INC HL ;ansonsten aufrunden
KeyRedox8: LD A,L
OR H ;Redox-Wert = 0?
JR NZ,KeyRedox9 ;Nein =>
LD A,22h
JP MakeErrCode ;0 Volt Redox-Wert eingegeben
KeyRedox9: LD DE,509 ;509mV = maximaler Redox-Wert
XOR A
PUSH HL
SBC HL,DE
POP HL
JR C,KeyRedox10
LD A,21h
JP MakeErrCode ;Redox-Wert zu groß!
KeyRedox10: RR H ;Redox-Wert / 2
RR L
LD (IX+SollRedox),L ;Soll-Redoxwert setzen
CALL CalcSollChecksum ;Prüfsumme über die Sollwerte errechnen
LD (SollChecksum),DE ;und merken
SET 7,(IX+KLED) ;"Setzen" aus
JP DispRedox ;Potential anzeigen
;"Leitwert"-Taste gedrückt
KeyLeitwert: RES 0,(IX+Flags) ;Zahleingabe aus
BIT 5,(IX+KLED) ;"Momentan"?
JR NZ,KeyLeitwert1 ;Nein =>
LD A,(IX+KLED)
OR 9Fh ;Mometan und Manuell an lassen (Rest aus)
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR FBh ;LEDs bis auf Leitwert ausschalten
LD (IX+KLED+1),A
RES 2,(IX+KLED+1) ;Leitwert anschalten
LD (C000h),A
RET
KeyLeitwert1: BIT 7,(IX+KLED) ;"Setzen" an?
JR Z,KeyLeitwert3 ;Ja! =>
LD A,(IX+KLED)
OR 3Fh ;bis auf Manuell und Setzen alles ausschalten
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR EFh ;bis auf Kanal 1 alles ausschalten
LD (IX+KLED+1),A
RES 2,(IX+KLED+1) ;Leitwert anschalten
IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
JR Z,KeyLeitwert2 ;Meerwasser =>
LD L,(IX+SollLeitwertS) ;Soll-Leitwert (Süßwasser)
JP DispLeitw
KeyLeitwert2: LD L,(IX+SollLeitwertM) ;Soll-Leitwert (Meerwasser)
JP DispLeitw
KeyLeitwert3: BIT 5,(IX+KLED+1) ;"Kanal 2"?
JR NZ,KeyLeitwert4 ;Nein =>
RES 2,(IX+KLED+1) ;Leitwert an
LD (C000h),A
RET
KeyLeitwert4: RES 2,(IX+KLED+1) ;Leitwert an
LD A,(IX+KLED)
OR 3Fh ;bis auf Manuell und Setzen alles ausschalten
LD (IX+KLED),A
LD A,(IX+KLED+1)
OR FBh ;bis auf Leitwert alles ausschalten
LD (IX+KLED+1),A
IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
JR Z,KeyLeitwert15 ;Meerwasser =>
LD A,(IX+DPunkt) ;Dezimalpunkt
CP DFh ;an 2.Stelle?
JR NZ,KeyLeitwert5 ;Nein =>
LD A,(IX+Display)
CP 5 ;5?
JR C,KeyLeitwert13
LD L,1
JR KeyLeitwert14
KeyLeitwert5: CALL GetNumInput
DEC IY
LD A,D
CP 0
JR Z,KeyLeitwert6 ;0 oder 1 Dezimalpunkt?
CP 1 ;Nein =>
JR Z,KeyLeitwert7
LD A,26h
JP MakeErrCode ;zu viele Dezimalpunkte beim Leitwert
KeyLeitwert6: LD IY,InputBuf+6
LD B,2
JR KeyLeitwert8
KeyLeitwert7: LD A,E
SUB 4
JR Z,KeyLeitwert10
JR C,KeyLeitwert10
LD B,A
KeyLeitwert8: LD A,0
PUSH IY
KeyLeitwert9: OR (IY-3) ;Ziffern vor der erwarteten Eingabe zusammen 'OR'n
DEC IY
DJNZ KeyLeitwert9
POP IY
CP 0
JR Z,KeyLeitwert10
LD A,24h
JP MakeErrCode ;Leitwert zu groß!
KeyLeitwert10: CALL ConvertInput
LD A,(IY+1) ;4.Ziffer
CP 5 ;>= 5?
JR C,KeyLeitwert11 ;Nein =>
INC HL ;aufrunden
KeyLeitwert11: LD DE,255
PUSH HL
XOR A
SBC HL,DE ;Leitwert >= 255? (2550 µS)
POP HL
JR C,KeyLeitwert12 ;Nein =>
LD A,24h
JP MakeErrCode ;Leitwert zu groß!
KeyLeitwert12: LD A,L
OR H ;Leitwert = 0?
JR NZ,KeyLeitwert14 ;Nein =>
KeyLeitwert13: LD A,25h
JP MakeErrCode ;Leitwert zu klein
KeyLeitwert14: LD (IX+SollLeitwertS),L ;Soll-Leitwert (Süßwasser) setzen
CALL CalcSollChecksum ;Prüfsumme über die Sollwerte errechnen
LD (SollChecksum),DE ;und merken
SET 7,(IX+KLED) ;"Setzen" aus
JP DispLeitw
;Leitwert für Meerwasser:
KeyLeitwert15: CALL GetNumInput
LD A,D
CP 0
JR Z,KeyLeitwert16
CP 1
JR Z,KeyLeitwert17
LD A,26h
JP MakeErrCode ;Dezimalpunktfehler beim Leitwert
KeyLeitwert16: LD IY,InputBuf+7
KeyLeitwert17: LD B,E
LD A,0
INC IY
PUSH IY
KeyLeitwert18: OR (IY-3)
DEC IY
DJNZ KeyLeitwert18
POP IY
CP 0
JR Z,KeyLeitwert19
LD A,24h
JP MakeErrCode ;Leitwert zu groß
KeyLeitwert19: CALL ConvertInput
LD A,(IY+1) ;3.Ziffer
CP 5 ;>= 5?
JR C,KeyLeitwert20 ;Nein =>
INC HL ;aufrunden
KeyLeitwert20: LD DE,353
XOR A
SBC HL,DE ;35.3mS abziehen
JR NC,KeyLeitwert21 ;Unterlauf? Nein =>
LD A,25h
JP MakeErrCode ;Leitwert zu klein
KeyLeitwert21: ADC HL,DE ;wieder dazuaddieren
LD DE,601
XOR A
SBC HL,DE ;60.1mS abziehen
JR C,KeyLeitwert22 ;Überlauf? Nein =>
LD A,24h
JP MakeErrCode ;Leitwert zu groß
KeyLeitwert22: ADC HL,DE
LD DE,350 ;35.0mS abziehen
SBC HL,DE
LD (IX+SollLeitwertM),L ;Soll-Leitwert (Meerwasser)
CALL CalcSollChecksum ;Prüfsumme über die Sollwerte errechnen
LD (SollChecksum),DE ;und merken
SET 7,(IX+KLED) ;"Setzen" aus
JP DispLeitw
;String ab HL ins Display übertragen
SetDisplayString:
LD BC,6
LD DE,Display
LDIR ;String ins Display
INC DE
INC DE
INC DE
LDI ;Dezimalpunkte übertragen
SET 4,(IX+Flags) ;keine Zahl im Display
RET
;Kanal 1-Regelung
Kanal1Regel:
LD A,(IX+Uni1Flag)
CP 55h ;Universal-Timer?
JP Z,UniTimer ;Ja =>
CP AAh ;Redox-Regelung?
JR Z,Kanal1Regel1 ;Ja =>
SCF
RET
Kanal1Regel1: CALL UniTimer
RET C ;nichts gefunden =>
LD A,(IX+SollRedox) ;Soll-Redoxwert
BIT 3,(IX+WarnLED) ;Kanal 1-LED an?
JR NZ,Kanal1Regel2 ;Nein =>
ADD A,1 ;Soll-Wert um 0.5µV erhöhen, wenn Regelung bereits an
Kanal1Regel2: CP (IX+IstRedox) ;mit Sollwert vergleichen
RET
;Kanal 2-Regelung
Kanal2Regel:
LD A,(IX+Uni2Flag)
CP 55h ;Universal-Timer?
JP Z,UniTimer ;Ja =>
CP AAh ;Leitwert-Regelung?
JR Z,Kanal2Regel1 ;Ja =>
SCF
RET
Kanal2Regel1: CALL UniTimer
RET C ;nichts gefunden =>
LD A,(IX+IstTemp) ;Ist-Temp-Wert
CP FFh
JR Z,Kanal2Regel2 ;außerhalb des Meßbereiches?
CP 0
JR Z,Kanal2Regel2 ;Ja =>
LD D,(IX+LeitwertKomp) ;kompensierter Leitwert
JR Kanal2Regel3
Kanal2Regel2: LD D,(IX+IstLeitw) ;Ist-Leitwert
Kanal2Regel3: IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
JR Z,Kanal2Regel4 ;Meerwasser =>
LD B,(IX+SollLeitwertS) ;Soll-Leitwert (Süßwasser)
JR Kanal2Regel5
Kanal2Regel4: LD B,(IX+SollLeitwertM) ;Soll-Leitwert (Meerwasser)
Kanal2Regel5: LD A,(IX+Uni2Flag2)
CP AAh ;Aus-Regelung
JR Z,Kanal2Regel8
CP 55h ;Ein-Regelung
JR Z,Kanal2Regel6
SCF ;Regelung illegal => raus
RET
Kanal2Regel6: LD A,B
BIT 0,(IX+WarnLED) ;Kanal 2-LED an?
JR Z,Kanal2Regel7 ;Ja =>
ADD A,2 ;Soll-Wert um 2 erhöhen, wenn Regelung bereits an
Kanal2Regel7: CP D ;mit Sollwert vergleichen
CCF
RET
Kanal2Regel8: LD A,B
BIT 0,(IX+WarnLED) ;Kanal 2-LED an?
JR NZ,Kanal2Regel9 ;Nein =>
ADD A,2 ;Soll-Wert um 2 erhöhen, wenn Regelung bereits an
Kanal2Regel9: CP D ;mit Sollwert vergleichen
RET
;Temperatur-Kompensation des Leitwertes errechnen (er weicht etwa 2% pro Grad Temperatur-Änderung
;von 25° vom Sollwert ab)
TempKomp: LD HL,65
LD (Mult24),HL
LD C,(IX+IstTemp) ;Ist-Temp-Wert (= (Temperatur-10.0°)*10)
CALL Mult24Bit
LD HL,42518
LD DE,(Mult24Erg) ;DE = 42518 - Ist-Temp * 65 (Ist-Temp = 25°: DE = 8000h = 1)
XOR A
SBC HL,DE ;DE: Bit 15 = 1, Bit 14...0 = Nachkommastellen
LD (Mult24),HL ;als neuen Multiplikator merken
PUSH HL
LD C,(IX+IstLeitw) ;Ist-Leitwert als Multiplikant
CALL TempKomp3 ;= 2 * Kompensations-Wert (= ganzer Anteil im oberen Byte!)
POP HL ;Leitwert = Mess-Leitwert * (1 - 2% * (Temp - 25°))
LD A,(IX+LeitwertKomp) ;Kompensations-Wert holen
CP FFh
RET Z ;ungültig => raus
CP 0
RET Z
IN C,(C)
BIT 5,C ;Süßwasser/Meerwasser-Schalter abfragen
RET NZ ;Süßwasser => raus
LD C,175
LD (Mult24),HL
CALL Mult24Bit ;(Multiplikator * 175) * 2
LD HL,(Mult24Erg+1)
ADD HL,HL
LD A,H
SUB 175
ADD A,A ;((Erg/256) - 175) * 2
JP P,TempKomp1 ;Positiv =>
CPL ;negieren
LD B,A
LD A,(IX+LeitwertKomp) ;Temp.Kompensation holen
SUB B
JR NC,TempKomp2 ;Wert groß genug? Ja =>
LD A,0 ;Unterlauf der Kompensation!
JR TempKomp2
TempKomp1: ADD A,(IX+LeitwertKomp) ;jetzige Temp.Kompensation dazu
JR NC,TempKomp2 ;Überlauf? Nein =>
LD A,FFh
TempKomp2: LD (IX+LeitwertKomp),A ;Temp.Kompensation setzen
RET
TempKomp3: CALL Mult24Bit
LD HL,(Mult24Erg+1);16-Bit Kompensation holen
BIT 7,H ;Bit 15 gesetzt (Wert zu groß)
JR Z,TempKomp5 ;Nein =>
TempKomp4: LD (IX+LeitwertKomp),FFh ;Temp.Kompensation ungültig!
RET
TempKomp5: ADD HL,HL ;Wert * 2
LD A,H ;oberes Byte nehmen
CP FFh ;ungültig?
JR Z,TempKomp4 ;Ja =>
BIT 7,L ;Bit 7 gesetzt?
JR Z,TempKomp6 ;Nein =>
INC A ;aufrunden (auf 8 Bit)
CP FFh ;ungültig?
JR Z,TempKomp4 ;Ja =>
TempKomp6: LD (IX+LeitwertKomp),A ;Temp.Kompensation setzen
RET
;24 Bit Multiplikation (Mult24...Mult24+2) * C = (Mult24Erg...Mult24Erg+2)
Mult24Bit: LD (C000h),A
LD B,4
LD HL,Mult24Erg+2
Mult24Bit1: LD (HL),0 ;Ergebniss und Buffer löschen
DEC HL
DJNZ Mult24Bit1
LD B,8 ;8 Bits
Mult24Bit2: LD HL,Mult24 ;Multiplikator
LD DE,Mult24Erg ;Ergebnis
RRC C ;Temperatur nach rechts ins Carry schieben
JR NC,Mult24Bit3
LD A,(DE)
ADD A,(HL)
LD (DE),A
INC HL ;(DE) = (DE)+(HL) (16 Bit Addition mit 24 Bit Ergebnis)
INC DE
LD A,(DE)
ADC A,(HL)
LD (DE),A
INC HL
INC DE
LD A,(DE)
ADC A,(HL)
LD (DE),A
LD HL,Mult24
Mult24Bit3: SLA (HL)
INC HL
RL (HL) ;Summand * 2 (24 Bit)
INC HL
RL (HL)
DJNZ Mult24Bit2 ;8 mal durchlaufen (8 Bit Multiplikant)
LD (C000h),A
RET
;Eingabe aus dem Display holen und Dezimalpunkte auswerten
;D-Register = Anzahl der Punkte
;IY zeigt auf die Nachkommastellen
GetNumInput: LD A,0
LD DE,InputBuf
LD (DE),A ;Byte 1 und 2 im Buffer löschen
INC DE
LD (DE),A
INC DE
LD HL,Display
LD BC,6
LDIR ;Anzeige in den Buffer (Byte 3...8) übertragen
LD (DE),A ;Byte 9 und 10 im Buffer löschen
INC DE
LD (DE),A
LD IY,InputBuf+7 ;Ptr auf die letzte Ziffer
LD C,(IX+DPunkt) ;Dezimalpunkte holen
LD D,0 ;Anzahl der Punkte = 0
LD B,6 ;maximal 6 Punkte auswerten
GetNumInput1: LD E,B ;Position des _letzten_ Punktes (= 6.Stelle)
BIT 0,C ;Punkt gesetzt?
JR Z,GetNumInput2 ;Ja (low-active!) => Nachkommastellenanfang gefunden
RR C ;Punkte eine Position nach rechts
DEC IY ;IY zeigt auf die letzte Vorkommastelle
DJNZ GetNumInput1 ;weiter nach Dezimalpunkt suchen
RET
GetNumInput2: INC D ;ein Dezimalpunkt mehr...
GetNumInput3: DJNZ GetNumInput4 ;alle Punktpositionen durch? Nein =>
RET
GetNumInput4: RR C ;Punkte eine Position nach rechts
BIT 0,C ;Punkt gesetzt?
JR NZ,GetNumInput3 ;Nein (low-active!) => (nächste Position)
JR GetNumInput2 ;Punkt zählen
StrrErE: DEFB 1Fh,13h,0Eh,1Ch,13h,0Eh,F6h ;" rE-rE"
StrLrEIN: DEFB 11h,13h,1Ch,0Eh,01h,1Eh,EFh ;"Lr-EIN"
StrLrAUS: DEFB 11h,13h,1Ch,0Ah,14h,05h,EFh ;"Lr-AUS"
StrLrUNI1: DEFB 1Fh,14h,1Eh,01h,1Ch,01h,FBh ;" UNI-1"
StrLrUNI2: DEFB 1Fh,14h,1Eh,01h,1Ch,02h,FBh ;" UNI-2"
Str6Space: DEFB 1Fh,1Fh,1Fh,1Fh,1Fh,1Fh,FFh ;" "
IF NewVersion
StrFEHL16: DEFB 0Fh,0Eh,10h,11h,01h,06h,FBh ;"FEHL16"
ELSE
StrFEHL16: DEFB 0Fh,0Eh,10h,11h,01h,06h,FFh ;"FEHL16"
ENDIF
Str6Minus: DEFB 1Ch,1Ch,1Ch,1Ch,1Ch,1Ch,FFh ;"------"
IF NewVersion
StrFEHL15: DEFB 0Fh,0Eh,10h,11h,01h,05h,FBh ;"FEHL15"
ELSE
StrFEHL15: DEFB 0Fh,0Eh,10h,11h,01h,05h,FFh ;"FEHL15"
ENDIF
;Versionsdatum im LED-Format
IF NewVersion
VersionNoDisp: DEFB 8Eh,BFh,FFh,79h,90h,C0h ;"F- 1.90"
ELSE
VersionNoDisp: DEFB 8Eh,BFh,FFh,79h,80h,90h ;"F- 1.89"
ENDIF
;Font => LED-Tabelle
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
FontLEDTable: DEFB C0h,F9h,A4h,B0h,99h,92h,82h,F8h,80h,90h,88h,83h,C6h,A1h,86h,8Eh
DEFB 89h,C7h,8Ch,AFh,C1h,8Dh,E3h,ABh,9Ch,A3h,87h,FEh,BFh,F7h,C8h,FFh
; H L P r U µ u n ° o /F /A - _ N ' '
;Rechentabelle Binär => Dezimal
BinDezTable: DEFW 0001h,0002h,0004h,0008h,0016h,0032h,0064h
DEFW 0128h,0256h,0512h,1024h,2048h,4096h,8192h
BinDezTableEnd:
;Tastaturtabelle
TastaturTab:
; "." "3" "6" "9" "0" "2" "5" "8" "*" "1" "4" "7"
DEFW KeyPunkt,8003h,8006h,8009h,8000h,8002h,8005h,8008h,KeyStern,8001h,8004h,8007h
; "Re" "Lw" "Tp" "pH" "CO2" "Li" "K2" "K1"
DEFW KeyRedox,KeyLeitwert,KeyTemperatur,KeyPh,KeyCO2,KeyLicht,KeyKanal2,KeyKanal1
; "Aus" "Ein" "Nacht" "Tag" "Setzen" "Manuell" "Momentan" "Zeit"
DEFW KeyAus,KeyEin,KeyNacht,KeyTag,KeySetzen,KeyManuell,KeyMomentan,KeyZeit
SpezKeyTable: DEFB FFh,FEh,FDh,FFh,FFh,FFh,FEh ;"0" "1" "Setzen" - Seriennummer (= 283062)
DEFB PrintSerial>>8,PrintSerial
DEFB FBh,FEh,FFh,FFh,FFh,FFh,FEh ;"0" "6" "Setzen" - Soll-ROM-Prüfsumme (= 5Fd6)
DEFB PrintROMChksum>>8,PrintROMChksum
DEFB FDh,FEh,FFh,FFh,FFh,FFh,FEh ;"0" "3" "Setzen" - Produktionsdatum (= 692)
DEFB PrintProdDatum>>8,PrintProdDatum
DEFB FFh,FEh,FBh,FFh,FFh,FFh,FEh ;"0" "4" "Setzen" - (1FF9h) = 12050
DEFB PrintUnknown>>8,PrintUnknown
DEFB FFh,FEh,F7h,FFh,FFh,FFh,FEh ;"0" "7" "Setzen" - Errechnete ROM-Prüfsumme
DEFB PrintRealChksum>>8,PrintRealChksum
SpezKeyLicht: DEFB FFh,FEh,FFh,FFh,FDh,FFh,FEh ;"0" "Licht" "Setzen" - alle LEDs anschalten
DEFB CheckAllLED>>8,CheckAllLED
DEFB FFh,FEh,FFh,FFh,FFh,FDh,FEh ;"0" "Ein" "Setzen" - alle Relais testen
DEFB CheckDosen>>8,CheckDosen
IF NewVersion
DEFB FFh,FEh,FFh,FFh,FFh,FFh,FAh ;"0" "Momentan" "Setzen" - Computer zurücksetzen
DEFB ResetComputer>>8,ResetComputer
ENDIF
DEFB 00h
PrintSerial: CALL KeyStern
LD HL,SerialNo ;Seriennummer des Gerätes (6 BCD-Stellen)
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
PrintROMChksum: CALL KeyStern
LD HL,ROMChecksum ;Prüfsumme über das ROM (binäres Wort)
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
PrintProdDatum: CALL KeyStern
LD HL,ProduktDatum ;Produktionsdatum (oberes Byte: Monat, unteres Byte: Jahr)
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
PrintUnknown: CALL KeyStern
LD HL,Unknown ;???
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
PrintRealChksum:CALL KeyStern
LD HL,CalcChecksum
CALL PrintTime
LD (IX+DPunkt),FFh ;Dezimalpunkte aus
RET
;_ALLE_ LEDs am Bedienteil an
CheckAllLED: LD HL,KLED
LD B,9
CheckAllLED1: LD (HL),0 ;2000h-2008h löschen => alle LEDs an
INC HL
DJNZ CheckAllLED1
CheckAllLED2: LD HL,SpezKeyLicht
LD DE,KeyboardMatrix
LD B,7
CheckAllLED3: LD A,(DE)
OR F0h
CP (HL)
JR NZ,CheckAllLED4 ;anlassen, solange die Tastenkombination gedrückt wird
INC HL
INC DE
DJNZ CheckAllLED3
LD (C000h),A
JR CheckAllLED2
CheckAllLED4: CALL KeyStern ;Display löschen
SET 6,(IX+KLED) ;Manuell-LED ausschalten
RET
;_ALLE_ Steckdosen an/auschalten
CheckDosen: IF NewVersion
IN A,(C) ;Sperre gesetzt?
BIT 4,A ;Nein! =>
JR NZ,CheckDosen0
JP KeySetzen1 ;Fehler 99!
ENDIF
CheckDosen0: LD A,(004Eh) ;??? sollte wohl (IX+Steckdosen) heissen (ist eh unnötig)
LD C,A
LD A,0
CALL SetDoseStatus ;alle Steckdosen aus
LD B,3
LD A,1
CheckDosen1: CALL SetDoseStatus ;3 Steckdosen (CO2, Heizung, Licht) nacheinander an
SLA A
DJNZ CheckDosen1
SLA A
CALL SetDoseStatus ;4.Steckdose (Kanal 1) an
SRL A
CALL SetDoseStatus ;5.Steckdose (Kanal 2) an
LD A,1Fh
CALL SetDoseStatus ;alle Steckdosen aus
LD A,C
LD (004Eh),A ;??? sollte wohl (IX+Steckdosen) heissen (ist eh unnötig)
RET
SetDoseStatus: LD (E000h),A ;Port schreiben
PUSH BC
LD B,0
SetDoseStatus1: LD (C000h),A ;kleine Pause
HALT
DJNZ SetDoseStatus1
POP BC
RET
;Computer zurücksetzen
ResetComputer: IF NewVersion
IN A,(C) ;Sperre gesetzt?
BIT 4,A ;Nein! =>
JR NZ,ResetComputer1
JP KeySetzen1 ;Fehler 99!
ResetComputer1: JP ResetVars
ENDIF
;Sprungtabelle für die Ausgabe eines Meßwertes im Akku
DoDispMessTab: DEFW DispPh,DispTemp,DispLeitw,DispRedox
IF !NewVersion
; 40h,"PAUL UND ULLI P0PPEN HANNA UND ELLI",42h,"SIE HABEN SPASS AN BUSEN UND PO",42h,42h,"OO LA-LA",41h
MsgFutura: DEFB 40h,12h,0Ah,14h,11h,1Fh,14h,17h,0Dh,1Fh,14h,11h,11h,01h,1Fh,12h
DEFB 00h,12h,12h,0Eh,1Eh,1Fh,10h,0Ah,1Eh,1Eh,0Ah,1Fh,14h,17h,0Dh,1Fh
DEFB 0Eh,11h,11h,01h,42h,05h,01h,0Eh,1Fh,10h,0Ah,0Bh,0Eh,1Eh,1Fh,05h
DEFB 12h,0Ah,05h,05h,1Fh,0Ah,17h,1Fh,0Bh,14h,05h,0Eh,1Eh,1Fh,14h,17h
DEFB 0Dh,1Fh,12h,00h,42h,42h,00h,10h,1Fh,11h,0Ah,1Ch,11h,0Ah,41h
; 40h,"HALLO",42h,"SIE HABEN PAUSE",41h
MsgPause: DEFB 40h,10h,0Ah,11h,11h,00h,42h,05h,01h,0Eh,1Fh,10h,0Ah,0Bh,0Eh,1Eh
DEFB 1Fh,12h,0Ah,14h,05h,0Eh,41h
; 40h,"HUI-",42h,"DAS S0LL ABER SEHR HEISS SEIN",41h
MsgHeiss: DEFB 40h,10h,14h,01h,1Ch,42h,0Dh,0Ah,05h,1Fh,05h,00h,11h,11h,1Fh,0Ah
DEFB 0Bh,0Eh,13h,1Fh,05h,0Eh,10h,13h,1Fh,10h,0Eh,01h,05h,05h,1Fh,05h
DEFB 0Eh,01h,17h,41h
; 40h,"HUI-",42h,"DAS S0LL ABER SEHR SAUER SEIN",41h
MsgSauer: DEFB 40h,10h,14h,01h,1Ch,42h,0Dh,0Ah,05h,1Fh,05h,00h,11h,11h,1Fh,0Ah
DEFB 0Bh,0Eh,13h,1Fh,05h,0Eh,10h,13h,1Fh,05h,0Ah,14h,0Eh,13h,1Fh,05h
DEFB 0Eh,01h,17h,41h
; 40h,"HUI-",42h,"DA5 S0LL ABER SEHR BASISCH SEIN",41h
MsgBasis: DEFB 40h,10h,14h,01h,1Ch,42h,0Dh,0Ah,05h,1Fh,05h,00h,11h,11h,1Fh,0Ah
DEFB 0Bh,0Eh,13h,1Fh,05h,0Eh,10h,13h,1Fh,0Bh,0Ah,05h,01h,05h,0Ch,10h
DEFB 1Fh,05h,0Eh,01h,17h,41h
MsgMessdaten: DEFM "************************** Messdatenerfassung **************************"
DEFB 13,10,10
DEFM "(c) By FUTURA Aquarien-Systeme, KLEVE, Kalkarer Str.24 Tel. 02821/17574"
DEFB 13,10,10,3,'$'
MsgEscH4Lf: DEFB 1Bh,'H',10,10,10,10,'$'
MsgEscHEscJ: DEFB 1Bh,'H',1Bh,'J','$'
Msg6Space: DEFM " "
DEFB 13,10,10,'$'
MsgZeit: DEFM "ZEIT : $"
MsgPhWert: DEFM "PH-WERT: $"
MsgGrad: DEFM "GRAD : $"
MsgMikroS: DEFM "MIKRO-S: $"
MsgMilliS: DEFM "MILLI-S: $"
MsgMilliV: DEFM "MILLI-V: $"
MsgFehl: DEFM "FEHL.$"
MsgCopyright: DEFM "Copyrigt (c) 1989 by Ulrich Forke & FUTURA Aquariensysteme"
DEFB 13,10
DEFM "4190 Kleve, Deutschland"
DEFB 13,10
DEFM "Die Verwendung dieses Programms oder Teilen davon ist nicht gestattet !"
DEFB 13,10
ENDIF
ORG ROMTop
SerialNo: DEFB 62h,30h,28h ;Seriennummer (= 283062)
ROMChecksum: DEFB D6h,5Fh,00h ;Prüfsumme über das ROM, "5Fd6"
ProduktDatum: DEFB 92h,06h,00h ;Produktionsdatum 6.92
Unknown: DEFB 50h,20h,01h ;??? (= 12050)
PRINT "Ende..."