summaryrefslogtreecommitdiff
path: root/ERICH_VER_0.1.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'ERICH_VER_0.1.ASM')
-rw-r--r--ERICH_VER_0.1.ASM645
1 files changed, 645 insertions, 0 deletions
diff --git a/ERICH_VER_0.1.ASM b/ERICH_VER_0.1.ASM
new file mode 100644
index 0000000..1ae2a7b
--- /dev/null
+++ b/ERICH_VER_0.1.ASM
@@ -0,0 +1,645 @@
+; #define Mengenlehreuhr
+
+#include <P16f872.INC>
+
+ __CONFIG 0x3B39
+
+Stunde Equ 0x20 ; aktuelle Stunde
+Minute Equ 0x21 ; aktuelle Minute
+Sekunde Equ 0x22 ; aktuelle Sekunde
+dreiMSL Equ 0x23 ; 3ms-Zaehler (eigtl. 10/3 ms) low-Teil
+dreiMSH Equ 0x24 ; 3ms-Zaehler (eigtl. 10/3 ms) high-Teil
+weiterDML Equ 0x25 ; Sollwert fuer 3ms-Zaehler beim Warten low-Teil
+weiterDMH Equ 0x26 ; Sollwert fuer 3ms-Zaehler beim Warten high-Teil
+weiterT1L Equ 0x27 ; Sollwert fuer Timer1Zaehler beim Warten low-Teil
+weiterT1H Equ 0x28 ; Sollwert fuer Timer1Zaehler beim Warten high-Teil
+tara Equ 0x29 ; zum Tarieren der Zeitkonstante
+dZFlL Equ 0x2A ; 3ms-Zaehlerstand bei letzter Flanke low-Teil
+dZFlH Equ 0x2B ; 3ms-Zaehlerstand bei letzter Flanke high-Teil
+Stati Equ 0x2C ; 0: letzter/aktueller Pegel der DCF77-Empfängers
+ ; 1: Fehler innerhalb der letzten Funkminute
+ ; 2: MEZ/MESZ-Umstellung am Ende der Stunde
+ ; 3: MESZ?
+ ; 4: Schaltsekunde am Ende der Stunde
+ ; 6: letzte Minute kam per Funk
+ ; 7: letzte Stunde kam per Funk
+tmpL Equ 0x2D ; temporaerer Speicher
+tmpH Equ 0x2E ; temporaerer Speicher
+Spalten Equ 0x2F ; zu aktivierende Spalten
+Zeilen Equ 0x30 ; zu aktivierende Zeile(n)
+dat0 Equ 0x31 ; Funkdaten, Bit 0..7
+dat1 Equ 0x32 ; Funkdaten, Bit 8..15
+dat2 Equ 0x33 ; Funkdaten, Bit 16..23
+dat3 Equ 0x34 ; Funkdaten, Bit 24..31
+dat4 Equ 0x35 ; Funkdaten, Bit 32..39
+dat5 Equ 0x36 ; Funkdaten, Bit 40..47
+dat6 Equ 0x37 ; Funkdaten, Bit 48..55
+dat7 Equ 0x38 ; Funkdaten, Bit 56..58 bzw. 63
+
+ GOTO Anfang
+ RETFIE
+
+Anfang ; nach den Interrupts
+
+ BCF STATUS, RP0
+ BCF STATUS, RP1 ; Bank0
+
+ CLRF Stunde ; eigene Variablen initialisieren
+ CLRF Minute
+ CLRF Sekunde
+ MOVLW 0x12
+ MOVWF Stunde
+ MOVLW 0x34
+ MOVWF Minute
+ MOVLW 0x56
+ MOVWF Sekunde
+
+ CLRF dat0
+ CLRF dat1
+ CLRF dat2
+ CLRF dat3
+ CLRF dat4
+ CLRF dat5
+ CLRF dat6
+ CLRF dat7
+
+ CLRF dreiMSH
+ CLRF dreiMSL
+ MOVLW 0x2C
+ MOVWF weiterDML
+ MOVLW 0x01
+ MOVWF weiterDMH
+ CLRF weiterT1L
+ CLRF weiterT1H
+ CLRF Stati
+ BSF Stati, 1
+ MOVLW 0x85
+ MOVWF tara ; eigentlich 5 1/3 (die 0x80 entspricht einer Null!)
+
+ CLRF PORTA ; I/O initialisieren
+ CLRF PORTB
+ CLRF PORTC
+
+ BSF STATUS, RP0 ; Bank 1
+
+ MOVLW 0x06 ; Port-A digital
+ MOVWF ADCON1
+ MOVLW 0x38 ; alles Ausgaenge bis auf A3, A4 und A5
+ MOVWF TRISA
+ CLRF TRISB ; alles Ausgaenge
+ CLRF TRISC ; alles Ausgaenge
+
+ BCF PIE1, TMR1IE ; Interrupt für Timer deaktivieren
+
+ BCF STATUS, RP0 ; Bank 0
+
+ MOVLW 0x01 ; Timer1 initialisieren
+ MOVWF T1CON
+; MOVLW 0xC0
+; MOVWF INTCON
+
+Multiplex
+
+#ifdef Mengenlehreuhr
+ MOVF Minute, 0
+ CALL BCD2Un
+ MOVWF Spalten
+ SWAPF Spalten, 1
+ MOVF Minute, 0
+ CALL BCD2Un5H
+ IORWF Spalten, 1 ; anzuzeigende Minutenteile
+
+; BTFSC Stati, 1 ; Funkfehler?
+; GOTO SekTaktAnzeigen
+
+ MOVF Stati, 0
+ MOVWF tmpL
+ RRF Stati, 0
+ ANDWF tmpL, 1 ; tmpL<6> = Stati<6> & Stati<7> (Funk korrekt?)
+ BTFSC Stati, 1
+ BCF tmpL, 6 ; tmpL<6> = Stati<6> & Stati<7> & NOT Stati<1> (Funk korrekt?)
+ RLF PORTA, 0
+ XORWF tmpL, 1 ; tmpL<6> = (Stati<6> & Stati<7> & NOT Stati<1>) XOR PORTA<5>
+ BTFSC tmpL, 6 ; Funksignal auf Sekunden-LED geben
+; BTFSC PORTA, 5
+ BSF Spalten, 3
+ GOTO ErsteZeileSetzen
+SekTaktAnzeigen
+ BTFSC Sekunde, 0 ; Sekunde auf Sekunden-LED geben
+ BSF Spalten, 3
+ErsteZeileSetzen
+#else
+ MOVF Sekunde, 0 ; Sekunde als nächstes anzeigen
+ MOVWF Spalten
+#endif
+ MOVLW 0x4
+ MOVWF Zeilen
+ CALL Wait
+
+#ifdef Mengenlehreuhr
+ MOVF Minute, 0
+ CALL BCD2Un5L
+ MOVWF Spalten
+#else
+ MOVF Minute, 0
+ MOVWF Spalten ; Minute als nächstes anzeigen
+#endif
+ MOVLW 0x2
+ MOVWF Zeilen
+ CALL Wait
+
+#ifdef Mengenlehreuhr
+ MOVF Stunde, 0
+ CALL BCD2Un5L
+ ANDLW 0xF0
+ MOVWF Spalten
+ MOVF Stunde, 0
+ CALL BCD2Un
+ IORWF Spalten, 1
+#else
+ MOVF Stunde, 0
+ ANDLW 0x3F
+ MOVWF Spalten ; Stunde als nächstes anzeigen
+ MOVF Stati, 0
+ MOVWF tmpL
+ RRF Stati, 0
+ ANDWF tmpL, 1
+ RLF PORTA, 0
+ XORWF tmpL, 1
+ BTFSC tmpL, 6
+ BSF Spalten, 6 ; Funksignal auf ZusatzLED geben
+#endif
+ MOVLW 0x1
+ MOVWF Zeilen
+ CALL Wait
+
+ GOTO Multiplex
+
+; Unterprogramme
+
+Sek ; Sekunde eins weiter stellen
+
+ BTFSC PORTA, 3 ; Tastendruck?
+ CALL Std
+ BTFSC PORTA, 4
+ CALL Min
+
+ INCF Sekunde, 1
+ MOVLW 0x0F ; 0x0F-Teil von Sekunde anschauen
+ ANDWF Sekunde, 0
+ SUBLW 0x0A ; = A ?
+ BTFSC STATUS, Z
+ GOTO Sek10 ; neue 10Sek!
+
+ RETURN ; Sek erfolgreich erhöht
+
+Sek10
+ MOVLW 0x10 ; Sekundenzehner weiter stellen
+ ADDWF Sekunde, 1
+ MOVLW 0xF0 ; Sekundeneiner löschen
+ ANDWF Sekunde, 1
+ MOVLW 0x60 ; = 60 ?
+ SUBWF Sekunde, 0
+ BTFSC STATUS, Z
+ GOTO Min ; neue Minute!
+
+ RETURN ; erfolgreiche neue 10Sek
+
+Min ; Minute eins weiter stellen
+ MOVLW 0x3F
+ ANDWF Stati, 1 ; Funkmin. & Funkstd. zurücksetzen
+ CLRF Sekunde
+ INCF Minute, 1
+ MOVLW 0x0F ; 0x0F-Teil von Minute anschauen
+ ANDWF Minute, 0
+ SUBLW 0x0A ; = A ?
+ BTFSC STATUS, Z
+ GOTO Min10 ; neue 10Min!
+
+ RETURN ; Min erfolgreich erhöht
+
+Min10
+ MOVLW 0x10 ; Minutenzehner weiter stellen
+ ADDWF Minute, 1
+ MOVLW 0xF0 ; Minuteneiner löschen
+ ANDWF Minute, 1
+ MOVLW 0x60 ; = 60 ?
+ SUBWF Minute, 0
+ BTFSC STATUS, Z
+ GOTO Std ; neue Stunde!
+
+ RETURN ; erfolgreiche neue 10Min
+
+Std ; Stunde eins weiter stellen
+ BTFSC Stati, 4 ; Schaltsekunde?
+ INCF Sekunde, 1
+ BCF Stati, 4 ; und rücksetzen
+
+ BTFSS Stati, 2 ; ME(S)Z-Umstellung?
+ GOTO keineSZUmstellung
+ BCF Stati, 2 ; rücksetzen
+ MOVLW 0x08
+ XORWF Stati, 1 ; ME(S)Z-Merker umschalten
+ BTFSC Stati, 3
+ INCF Stunde, 1 ; etwas rabiat, sollte bei einer Umstellung zwischen
+ ; 2 und 3 Uhr aber funktionieren
+ BTFSS Stati, 3
+ DECF Stunde, 1 ; dito
+
+keineSZUmstellung
+
+ CLRF Minute
+ INCF Stunde, 1
+ MOVLW 0x0F ; 0x0F-Teil von Stunde anschauen
+ ANDWF Stunde, 0
+ SUBLW 0x0A ; = A ?
+ BTFSC STATUS, Z
+ GOTO Std10 ; neue 10Std!
+
+ MOVLW 0x24 ; = 24 ?
+ SUBWF Stunde, 0
+ BTFSC STATUS, Z
+ CLRF Stunde ; neuer Tag
+
+ RETURN ; Std erfolgreich erhöht
+
+Std10
+ MOVLW 0x10 ; Stundenzehner weiter stellen
+ ADDWF Stunde, 1
+ MOVLW 0xF0 ; Stundeneiner löschen
+ ANDWF Stunde, 1
+
+ RETURN ; erfolgreiche neue 10Std
+
+Wait
+ MOVF tara, 0
+ ADDWF weiterT1L, 1 ; + (0x00;tara)
+ BTFSC STATUS, C
+ INCF weiterT1H, 1
+
+ MOVLW 0x80
+ ADDWF weiterT1L, 1 ; + (0x00;0x80)
+ BTFSC STATUS, C
+ INCF weiterT1H, 1
+
+ MOVLW 0x0C ; + (0x0C;0x00)
+ ADDWF weiterT1H, 1 ; Solltimerstand setzen (für 300Hz)
+
+WLoop
+ MOVF weiterT1H, 0
+ MOVWF tmpL
+
+ MOVF TMR1L, 0
+ SUBWF weiterT1L, 0
+ BTFSS STATUS, C
+ DECF tmpL, 1
+ MOVF TMR1H, 0
+ SUBWF tmpL, 1
+ BTFSS tmpL, 7 ; weiterT1 - TMR1 >= 0x8000 ("<0"), dann skippen
+
+ GOTO WLoop
+
+ MOVLW 0xF8
+ ANDWF PORTA, 1
+ MOVF Spalten, 0
+ MOVWF PORTB
+ MOVF Zeilen, 0
+ IORWF PORTA, 1
+
+ MOVLW 0xFF
+ BTFSS PORTA, 5
+ MOVLW 0x00
+ XORWF Stati, 0
+ ANDLW 0x01
+ BTFSS STATUS, Z
+ CALL FlankeGefunden
+
+ INCF dreiMSL, 1 ; 3MS zählen
+ BTFSC STATUS, Z
+ INCF dreiMSH, 1 ; 3*256MS zählen
+
+ MOVF weiterDMH, 0 ; weiterDM = dreiMS ?
+ SUBWF dreiMSH, 0
+ BTFSS STATUS, Z
+ RETURN ; nein !
+
+ MOVF weiterDML, 0
+ SUBWF dreiMSL, 0
+ BTFSS STATUS, Z
+ RETURN ; nein !
+ ; ja !
+ CALL setzeWeiterDM ; neue Marke setzen
+ CALL Sek ; neue Sekunde
+
+ RETURN ; Wait
+
+FlankeGefunden
+ MOVF dZFlH, 0
+ SUBWF dreiMSH, 0
+ MOVWF tmpH
+ MOVF dZFlL, 0
+ SUBWF dreiMSL, 0
+ BTFSS STATUS, C
+ DECF tmpH, 1
+ MOVWF tmpL ; tmp:= dreiMS - dzFl
+ BTFSS Stati, 0
+ GOTO warLow
+ BCF Stati, 0 ; war High-Pegel
+ MOVF tmpH, 0
+ BTFSS STATUS, Z ; tmp >= 0x0100 ?
+ GOTO periodenFehler ; Fehler!
+ MOVF tmpL, 0
+ SUBLW 0x4B ; tmp > 75? (entspricht 250 ms)
+ BTFSS STATUS, C
+ GOTO periodenFehler ; Fehler!
+ MOVLW 0x0A ; tmp < 10? (entspricht 33 ms)
+ SUBWF tmpL, 0
+ BTFSS STATUS, C
+ GOTO periodenFehler ; Fehler!
+ MOVLW 0x28
+ SUBWF tmpL, 0 ; tmp >= 40? (entspricht 133 ms) -> empfangenes Bit
+ RRF dat0, 1
+ RRF dat1, 1
+ RRF dat2, 1
+ RRF dat3, 1
+ RRF dat4, 1
+ RRF dat5, 1
+ RRF dat6, 1
+ RRF dat7, 1
+ ; die Pegellänge interessiert bei low nicht
+ RETURN
+warLow
+ BSF Stati, 0 ; war Low-Pegel
+
+ MOVF tmpH, 0
+ BTFSC STATUS, Z ; tmp <= 0x00FF ? (= 0,85 s)
+ GOTO keineNeueFunkMinute
+ SUBLW 0x02
+ BTFSS STATUS, C ; tmp > 0x02FF ? (= 2,56 s)
+ GOTO periodenFehler ; Fehler!
+
+ BTFSS tmpH, 1 ; tmp <= 0x01FF ? (= 1,70 s)
+ GOTO keineNeueFunkMinute
+
+ BTFSS Stati, 1 ; wenn kein Fehler, dann
+ CALL neueFunkMinute
+ CLRF dat0 ; Funk-Werte initialisieren
+ CLRF dat1
+ CLRF dat2
+ CLRF dat3
+ CLRF dat4
+ CLRF dat5
+ CLRF dat6
+ CLRF dat7
+ BSF dat0, 7
+ BCF Stati, 1 ; Fehler zurücksetzen
+keineNeueFunkMinute
+
+ MOVF dreiMSH, 0 ; Überprüfung, ob neue Sekunde eingeleitet werden muss
+ SUBWF weiterDMH, 0
+ MOVWF tmpH
+ MOVF dreiMSL, 0
+ SUBWF weiterDML, 0
+ BTFSS STATUS, C
+ DECF tmpH, 1
+ MOVWF tmpL ; tmp := weiterDM - dreiMS
+
+ MOVF tmpH, 0
+ BTFSS STATUS, Z ; wenn tmp >= 0x0100
+ GOTO keineExtraSek ; dann gab's schon 'ne neue Sekunde vom Quarz
+ MOVF tmpL, 0
+ SUBLW 0x96
+ BTFSS STATUS, C ; wenn tmp >= 0x0096 (= 150)
+ GOTO keineExtraSek ; dann gab's schon 'ne neue Sekunde vom Quarz
+
+ BTFSS Stati,1 ; wenn der Funk spinnt, wird nicht an der Zeit gespielt!
+ CALL Sek
+keineExtraSek
+ BTFSS Stati,1 ; wenn der Funk spinnt, wird nicht an der Zeit gespielt!
+ CALL setzeWeiterDM ; neue Marke setzen
+ GOTO FlankenZeitSpeichern
+
+periodenFehler ; wenn die Pegelperiode nicht stimmt, muss
+ ; trotzdem mindestens die Zeitmarke gesetzt werden
+ BSF Stati, 1
+FlankenZeitSpeichern
+ MOVF dreiMSL, 0
+ MOVWF dZFlL
+ MOVF dreiMSH, 0
+ MOVWF dZFlH
+ RETURN ; FlankeGefunden
+
+neueFunkMinute
+ MOVLW 0x10 ; dat7, 5 ist das 0. Bit in Wikipediazählweise
+ XORWF dat7, 0
+ ANDLW 0x3F
+ BTFSS STATUS, Z ; Anfang nicht korrekt durchgeschoben?
+ RETURN
+
+ BTFSS dat4, 1 ; 20. Bit sollte immer 1 sein!
+ RETURN
+
+ BCF Stati, 2
+ BTFSC dat5, 5 ; 16. Bit (MEZ/MESZ-Umstellung)
+ BSF Stati, 2
+
+ MOVLW 0xC0
+ ANDWF dat5, 0
+ XORLW 0x40
+ BTFSC STATUS, Z ; 17. & 18. Bit -> Sommerzeit!
+ BSF Stati, 3
+ XORLW 0xC0
+ BTFSC STATUS, Z ; 17. & 18. Bit -> keine Sommerzeit!
+ BCF Stati, 3 ; Im Falle von Fehlern werden diese Bits ignoriert!
+
+ BCF Stati, 4
+ BTFSC dat4, 0 ; 19. Bit -> Schaltsekunde am Ende der Stunde?
+ BSF Stati, 4
+
+ RRF dat3, 0
+ MOVWF tmpH
+ RRF dat4, 0
+ MOVWF tmpL ; (dat3;dat4) eins verschoben merken
+ RRF tmpH, 1
+ RRF tmpL, 1 ; noch eins verschieben
+ MOVF tmpL, 0 ; -> bit21..bit28 (Minute mit Parität)
+ MOVWF tmpH ; Parität prüfen:
+ RRF tmpH, 1
+ XORWF tmpH, 1 ; benachbarte Bits XORen
+ MOVF tmpH, 0
+ RRF tmpH, 1
+ RRF tmpH, 1
+ XORWF tmpH, 1 ; Übernächste Nachbarn XORen
+ MOVF tmpH, 0
+ RRF tmpH, 1
+ RRF tmpH, 1
+ RRF tmpH, 1
+ RRF tmpH, 1
+ XORWF tmpH, 1 ; üüübernächste Nachbarn XORen
+ BTFSC tmpH, 0 ; gerade Parität!
+ GOTO Funkminutenfehler
+ MOVF tmpL, 0
+ ANDLW 0x0F
+ SUBLW 0x09
+ BTFSS STATUS, C ; Minuteneiner >9 ?
+ GOTO Funkminutenfehler
+ MOVF tmpL, 0
+ ANDLW 0x70
+ SUBLW 0x50
+ BTFSS STATUS, C ; Minutenzehner >5 ?
+ GOTO Funkminutenfehler
+ MOVF tmpL, 0
+ ANDLW 0x7F ; Parität löschen
+ MOVWF Minute ; Minute setzen
+ CLRF Sekunde ; Sekunde auf 0
+ CALL setzeWeiterDM ; Sekunde auf ,0
+ BSF Stati, 6
+Funkminutenfehler
+
+ RRF dat2, 0
+ RRF dat3, 0
+ MOVWF tmpL ; (dat3;dat4) eins verschoben merken
+ RRF tmpL, 0 ; noch eins verschieben
+ ANDLW 0x7F ; falsche Bits löschen
+ MOVWF tmpL ; -> bit29..bit25 (Stunde mit Parität)
+ MOVWF tmpH ; Parität prüfen:
+ MOVWF tmpH
+ RRF tmpH, 1
+ XORWF tmpH, 1 ; benachbarte Bits XORen
+ MOVF tmpH, 0
+ RRF tmpH, 1
+ RRF tmpH, 1
+ XORWF tmpH, 1 ; Übernächste Nachbarn XORen
+ MOVF tmpH, 0
+ RRF tmpH, 1
+ RRF tmpH, 1
+ RRF tmpH, 1
+ RRF tmpH, 1
+ XORWF tmpH, 1 ; üüübernächste Nachbarn XORen
+ BTFSC tmpH, 0 ; gerade Parität!
+ GOTO Funkstundenfehler
+ MOVF tmpL, 0
+ ANDLW 0x0F
+ SUBLW 0x09
+ BTFSS STATUS, C ; Stundeneiner >9 ?
+ GOTO Funkstundenfehler
+ MOVF tmpL, 0
+ ANDLW 0x30
+ SUBLW 0x20
+ BTFSS STATUS, C ; Stundenzehner >2 ?
+ GOTO Funkstundenfehler
+ MOVF tmpL, 0
+ ANDLW 0x3F
+ SUBLW 0x23
+ BTFSS STATUS, C ; Stunde >23 ? (ohne Einerüberprüfung!)
+ GOTO Funkstundenfehler
+ MOVF tmpL, 0
+ ANDLW 0x3F
+ MOVWF Stunde ; Stunde setzen
+ BSF Stati, 7
+Funkstundenfehler
+
+ RETURN ; neueFunkMinute
+
+setzeWeiterDM ; setzt weiterDM-Zähler auf nächste 1/300s-Zeit
+ MOVLW 0x01
+ ADDWF dreiMSH, 0
+ MOVWF weiterDMH ; high-Teil + 1
+ MOVLW 0x2C
+ ADDWF dreiMSL, 0 ; low-Teil + 44
+ BTFSC STATUS, C
+ INCF weiterDMH, 1 ; Übertrag
+ MOVWF weiterDML
+ ; -> /300
+
+ RETURN ; setzeWeiterDM
+
+#ifdef Mengenlehreuhr
+BCD2Un5L ; bcd zu unär (5er, low-teil)
+ SUBLW 0x09
+ SUBLW 0x04
+ BTFSC STATUS, DC ; 5er an?
+ GOTO BCD2Un5LUng
+ ADDLW 0x05
+ ANDLW 0xF0
+ BTFSC STATUS, Z ; =0 ?
+ RETLW 0x00
+ XORLW 0x10
+ BTFSC STATUS, Z ; =10 ?
+ RETLW 0xC0
+ XORLW 0x30
+ BTFSC STATUS, Z ; =20 ?
+ RETLW 0xF0
+ XORLW 0x10
+ BTFSC STATUS, Z ; =30 ?
+ RETLW 0xFC
+ RETLW 0xFF ; >=40
+BCD2Un5LUng ; 5er muss gesetzt werden
+ ANDLW 0xF0
+ BTFSC STATUS, Z ; =5 ?
+ RETLW 0x80
+ XORLW 0x10
+ BTFSC STATUS, Z ; =15 ?
+ RETLW 0xE0
+ XORLW 0x30
+ BTFSC STATUS, Z ; =25 ?
+ RETLW 0xF8
+ XORLW 0x10
+ BTFSC STATUS, Z ; =35 ?
+ RETLW 0xFE
+ RETLW 0xFF ; >=40
+
+BCD2Un5H ; bcd zu unär (5er, high-teil)
+ SUBLW 0x09
+ SUBLW 0x04
+ BTFSC STATUS, DC ; 5er an?
+ GOTO BCD2Un5HUng
+ ADDLW 0x05
+ ANDLW 0xF0
+ XORLW 0x50
+ BTFSC STATUS, Z ; =50 ?
+ RETLW 0x06
+ RETLW 0x00 ; <=40
+BCD2Un5HUng ; 5er muss gesetzt werden
+ ANDLW 0xF0
+ XORLW 0x40
+ BTFSC STATUS, Z ; =45 ?
+ RETLW 0x04
+ XORLW 0x10
+ BTFSC STATUS, Z ; =55 ?
+ RETLW 0x07
+ RETLW 0x00 ; <=40
+
+BCD2Un ; bcd zu unär (1er)
+ ANDLW 0x0F
+ BTFSC STATUS, Z ; =0 ?
+ RETLW 0x00
+ XORLW 0x01
+ BTFSC STATUS, Z ; =1 ?
+ RETLW 0x08
+ XORLW 0x03
+ BTFSC STATUS, Z ; =2 ?
+ RETLW 0x0C
+ XORLW 0x01
+ BTFSC STATUS, Z ; =3 ?
+ RETLW 0x0E
+ XORLW 0x07
+ BTFSC STATUS, Z ; =4 ?
+ RETLW 0x0F
+ XORLW 0x01
+ BTFSC STATUS, Z ; =5 ?
+ RETLW 0x00
+ XORLW 0x03
+ BTFSC STATUS, Z ; =6 ?
+ RETLW 0x08
+ XORLW 0x01
+ BTFSC STATUS, Z ; =7 ?
+ RETLW 0x0C
+ XORLW 0x0F
+ BTFSC STATUS, Z ; =8 ?
+ RETLW 0x0E
+ RETLW 0x0F
+
+#endif
+
+ END