Hier noch der 2. Teil:

Bibliothek (RP6DCFClockCClib.cc), Teil 2:
Code:
/**
 * DCF DECODER
 *
 * Dies ist der DCF77 Decoder.
 *
 * Der (abschaltbare) DCF Decoder in dieser Funktion decodiert die
 * DCF Informationen und stellt die Uhr mit den empfangenen Daten.
 *
 * Die Funktion decodeDCF() muss alle 10ms aufgerufen werden.
 *
 */
void decodeDCF(void)
{byte temp, dcfbit;
 static byte impulsdauer, alterpegel, paritaet;
 static byte dcfbitzaehler, dcfbitpuffer;
#ifdef WETTER
 static unsigned int wetterpuffer;
#endif
 static byte jahrpuffer, monatpuffer, wochentagpuffer, tagpuffer;
 static byte sommerzeitpuffer, stundepuffer, minutepuffer, dcfflagspuffer;
    if (!(dcfstatus & STATUS_DCF_AN)) {
        return;                         // DCF Decoder AUS!
    }
    // DCF77 Decoder:
    temp = Port_ReadBit(DCF_IN);        // DCF Eingang lesen
    if (temp == alterpegel) {           // Keine Pegeländerung
        impulsdauer++;
        if (impulsdauer >= (PAUSE_1900MS + (PAUSE_ABWEICHUNG * 3))) {
            impulsdauer = 0;
            dcfstatus = dcfstatus | STATUS_FEHLER;
        }
        return;                         // Ende DCF Decoder!
    }
    else {                              // Pegeländerung am Eingang
#ifdef REPARATUR
        // Nach 1ms Port neu lesen zum Erkennen von "Spikes":
        // (Spikes sind kurze Störsignale von elektr. Geräten)
        AbsDelay(1);                    // 1ms Verzögerung
        if (temp != Port_ReadBit(DCF_IN)) { // Keine Pegeländerung
            impulsdauer++;
	        return;
        }
#endif
        alterpegel = temp;
        dcfbit = BIT_FEHLER;
        if ((impulsdauer >= (PAUSE_900MS - PAUSE_ABWEICHUNG))
         && (impulsdauer < (PAUSE_900MS + PAUSE_ABWEICHUNG))) {
            dcfbit = BIT_0;             // Bit 0 decodiert
#ifdef DEBUG
            pause_0_laenge = impulsdauer;
#endif
        }
        if ((impulsdauer >= (PAUSE_800MS - PAUSE_ABWEICHUNG))
         && (impulsdauer < (PAUSE_800MS + PAUSE_ABWEICHUNG))) {
            dcfbit = BIT_1;             // Bit 1 decodiert
            paritaet++;
#ifdef DEBUG
            pause_1_laenge = impulsdauer;
#endif
        }
        if ((impulsdauer >= (PAUSE_1900MS - PAUSE_ABWEICHUNG))
         && (impulsdauer < (PAUSE_1900MS + PAUSE_ABWEICHUNG))) {
            dcfbit = LETZTESBIT_0;      // Letztes Bit 0 decodiert
#ifdef DEBUG
            letztepause_0_laenge = impulsdauer;
#endif
        }
        if ((impulsdauer >= (PAUSE_1800MS - PAUSE_ABWEICHUNG))
         && (impulsdauer < (PAUSE_1800MS + PAUSE_ABWEICHUNG))) {
            dcfbit = LETZTESBIT_1;      // Letztes Bit 1 decodiert
            paritaet++;
#ifdef DEBUG
        	letztepause_1_laenge = impulsdauer;
#endif
		}
		impulsdauer = 0;					  // Impulsdauer zurücksetzen
		if (dcfbit != BIT_FEHLER) {           // Kein DCF Bitfehler
            dcfbitpuffer = dcfbitpuffer >> 1; // Puffer nach rechts schieben
            dcfbitpuffer = dcfbitpuffer | (dcfbit & 0x80); // DCF Bit einfügen
			switch (dcfbitzaehler) {
#ifdef WETTER
				case  7 :
					wetterpuffer = dcfbitpuffer; // Wetter Infos (Bits 0..7)
                    if (wetterpuffer & 0x0001) {           // DCF Bit 0 == 1 ?
                        dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
                    }
					dcfbitpuffer = 0; break;
#endif
				case 14 :
#ifdef WETTER                                    // Wetter Infos (Bits 8..14)
					wetterpuffer = wetterpuffer | (dcfbitpuffer << 7);
#endif
					dcfstatus = dcfstatus & (~STATUS_TELEGRAMMINTAKT);
                    dcfbitpuffer = 0; break;
				case 20 :
					dcfflagspuffer = dcfbitpuffer >> 2;    // DCF Flags
                    if (dcfflagspuffer & FLAG_Z1) {        // Z1: Zeitzone
                        sommerzeitpuffer = 1;              // [1 = MESZ]
                        if (dcfflagspuffer & FLAG_Z2) {    // Z1 == Z2 ?
                            dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler!
                        }
                    }
                    else {
                        sommerzeitpuffer = 0;              // [0 = MEZ]
                        if (!(dcfflagspuffer & FLAG_Z2)) { // Z1 == Z2 ?
                            dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler!
                        }
                    }
					if (!(dcfflagspuffer & FLAG_S)) {      // Start Bit == 0 ?
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
                    dcfbitpuffer = 0;
					paritaet = 0; break;
				case 27 :
					minutepuffer = BCDtoDEC(dcfbitpuffer >> 1); // Minute
					if (minutepuffer > 59) {               // Minute > 59 ?
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
                    break;
                case 28 :
					if (!(paritaet & 1)) {                 // P1: Parität ok ?
                        dcfstatus = dcfstatus | STATUS_MINPARITAET;
                    }
                    dcfbitpuffer = 0;
					paritaet = 0; break;
				case 34 :
					stundepuffer = BCDtoDEC(dcfbitpuffer >> 2); // Stunde
					if (stundepuffer > 23) {               // Stunde > 23 ?
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
                    break;
                case 35 :
					if (!(paritaet & 1)) {                 // P2: Parität ok ?
                        dcfstatus = dcfstatus | STATUS_STDPARITAET;
                    }
                    dcfbitpuffer = 0;
					paritaet = 0; break;
				case 41 :
					tagpuffer = BCDtoDEC(dcfbitpuffer >> 2); // Tag
					if ((tagpuffer == 0) || (tagpuffer > 31)) {
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
					dcfbitpuffer = 0; break;
				case 44 :
					wochentagpuffer = dcfbitpuffer >> 5;   // Wochentag
					if ((wochentagpuffer == 0) || (wochentagpuffer > 7)) {
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
					dcfbitpuffer = 0; break;
				case 49 :
					monatpuffer = BCDtoDEC(dcfbitpuffer >> 3); // Monat
					if ((monatpuffer == 0) || (monatpuffer > 12)) {
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
					dcfbitpuffer = 0; break;
				case 57 :
					jahrpuffer = BCDtoDEC(dcfbitpuffer);   // Jahr
					if (jahrpuffer > 99) {
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
                    break;
                case 58 :
                    dcfstatus = dcfstatus | STATUS_DCFBIT58;
					if (!(paritaet & 1)) {                 // P3: Parität ok ?
                        dcfstatus = dcfstatus | STATUS_DATPARITAET;
                    }
                    break;
				case 59 :                                  // Schaltsekundenbit
					if ((dcfbitpuffer & 0x80) || (!(dcfflagspuffer & FLAG_A2))) {
						dcfstatus = dcfstatus | STATUS_FEHLER;     // -> Fehler!
					}
					break;
				case 60 :                                  // Mehr als 59 Bits?
                    dcfstatus = dcfstatus & (~STATUS_DCFBIT58);    // -> Fehler!
			}
			if (dcfbit & LETZTESBIT_0) { // Ein letztes Bit (Telegrammende):
				if ((!(dcfstatus & STATUS_FEHLER))
                 && (dcfstatus & STATUS_MINPARITAET)
				 && (dcfstatus & STATUS_STDPARITAET)
                 && (dcfstatus & STATUS_DATPARITAET)
				 && (dcfstatus & STATUS_DCFBIT58)) { // Telegramm fehlerfrei?
					dcfstatus = dcfstatus | STATUS_TELEGRAMMINTAKT; // Ja!
					validitaetszaehler++;
					if (validitaetszaehler >= validitaetsgrenze) {
						validitaetszaehler = validitaetsgrenze;
#ifdef WETTER
                        DCF_WEATHER = wetterpuffer;
#endif
                        dcfflags = dcfflagspuffer;
                        Clock_SetTime(stundepuffer, minutepuffer, 0,
                         CLOCK_CORR);                      // Uhr stellen!
                        DCF_DST = sommerzeitpuffer;
                        DCF_DOW = wochentagpuffer;
                        tagpuffer--;                       // Tag und Monat
                        monatpuffer--;                     // ... nullbasiert!
                        Clock_SetDate(tagpuffer, monatpuffer, jahrpuffer);
						dcfstatus = dcfstatus | STATUS_UHRGESTELLT;
					}
				}
				else {			 // Telegramm NICHT intakt oder plausibel:
					validitaetszaehler = 0; // Validitätszähler zurücksetzen
				}
                // Vorbereitung auf nächstes DCF Telegramm:
                dcfstatus = dcfstatus & (~(STATUS_FEHLER | STATUS_MINPARITAET
                 | STATUS_STDPARITAET | STATUS_DATPARITAET
                 | STATUS_DCFBIT58));       // 5 Status Bits löschen
                dcfbitpuffer = 0;
				dcfbitzaehler = 0;
			}
			else {               // Kein Telegramm Ende:
				dcfbitzaehler++; // Nächstes DCF Bit decodieren
			}
		} // Kein DCF Bitfehler
	} // Pegeländerung am Eingang
}

/******************************************************************************/
// Nützliche LCD Funktionen:

/**
 * SHOW CLOCK
 *
 * Format: Uhrzeit
 *         Datum
 *
 */
void showCLOCK(void)
{byte temp;
	setCursorPosLCD(0, 1);		// Zeile 1
    temp = Clock_GetVal(CLOCK_HOUR);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	writeCharLCD(':');
    temp = Clock_GetVal(CLOCK_MIN);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	writeCharLCD(':');
    temp = Clock_GetVal(CLOCK_SEC);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	if (dcfstatus & STATUS_UHRGESTELLT) {
		if (DCF_DST) {		    // MESZ?
			printLCD("  MESZ");
		}
		else {
			printLCD("   MEZ");
		}
	}
	setCursorPosLCD(1, 1);		// Zeile 2
	switch (DCF_DOW) {          // Wochentag
		case 1 : printLCD("Mo"); break;
		case 2 : printLCD("Di"); break;
		case 3 : printLCD("Mi"); break;
		case 4 : printLCD("Do"); break;
		case 5 : printLCD("Fr"); break;
		case 6 : printLCD("Sa"); break;
		case 7 : printLCD("So"); break;
		default : printLCD("--");
	}
	printLCD(", ");
    temp = Clock_GetVal(CLOCK_DAY) + 1; // Tag nullbasiert!
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	writeCharLCD('.');
    temp = Clock_GetVal(CLOCK_MON) + 1; // Monat nullbasiert!
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	printLCD(".20");
    temp = Clock_GetVal(CLOCK_YEAR);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
}

/**
 * SHOW STATUS
 *
 * Format: Status
 *         Uhrzeit
 *
 */
void showSTATUS(void)
{byte i, temp;
	setCursorPosLCD(0, 1);		// Zeile 1
	printLCD("Stat: ");
    temp = dcfstatus;
    for(i = 0; i < 8; i++) {
        if (temp & 0x80) {
            writeCharLCD('1');
        }
        else {
            writeCharLCD('0');
        }
        temp = temp << 1;
    }
	setCursorPosLCD(1, 1);		// Zeile 2
    temp = Clock_GetVal(CLOCK_HOUR);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	writeCharLCD(':');
    temp = Clock_GetVal(CLOCK_MIN);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	writeCharLCD(':');
    temp = Clock_GetVal(CLOCK_SEC);
	if (temp < 10) {
		writeCharLCD('0');
	}
	printIntegerLCD(temp);
	if (dcfstatus & STATUS_UHRGESTELLT) {
		if (DCF_DST) {		    // MESZ?
			printLCD("  MESZ");
		}
		else {
			printLCD("   MEZ");
		}
	}
}

#ifdef DEBUG
/**
 * SHOW DEBUG INFO
 *
 */
void showDEBUGINFO(void)
{
	setCursorPosLCD(0, 1);		// Zeile 1
	printLCD("P1/0: ");
	printIntegerLCD(pause_1_laenge);
	printLCD(" / ");
	printIntegerLCD(pause_0_laenge);
	printLCD("  ");
	setCursorPosLCD(1, 1);		// Zeile 2
	printLCD("L1/0: ");
	printIntegerLCD(letztepause_1_laenge);
	printLCD(" / ");
	printIntegerLCD(letztepause_0_laenge);
	printLCD("  ");
}
#endif

/******************************************************************************
 * Info
 * ****************************************************************************
 * Changelog:
 * - v. 1.0 (initial release) 13.06.2009 by Dirk
 *
 * ****************************************************************************
 */

/*****************************************************************************/
// EOF
Gruß Dirk