PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CCPRO M128: DCF Clock 2 (CompactC)



Dirk
13.06.2009, 15:46
Hier noch der 2. Teil:

Bibliothek (RP6DCFClockCClib.cc), Teil 2:

/**
* 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