diff options
Diffstat (limited to 'ERICH_VER_0.1.ASM')
-rw-r--r-- | ERICH_VER_0.1.ASM | 645 |
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 |