Source file: /~heha/basteln/PC/FunkUsb/dcf77franz10.zip/dcf77dec.cpp

#include "dcf77dec.h"
#include <avr/pgmspace.h>
#include <string.h>

DCF77Dec dcf77dec;

void DateTime::operator++() {
 asm volatile("rcall incMinute"::"z"(this):"r24","r25");
}

byte DateTime::operator=(const DateTime&o) {
 byte r;
 asm volatile("rcall copyDate$mov %0,r24":"=r"(r):"x"(this),"z"(&o):"r24","r25");
 return r;
}

unsigned DateTime::operator=(const DCF77Data&o) {
 unsigned Err;
 asm volatile("rcall checkConvert$movw %A0,r22":"=r"(Err):"x"(this),"z"(&o):"r18","r19","r22","r23","r24","r25");
 return Err;
}

#define setBit(ptr,bit) ({void*X=(ptr);byte B=(bit);asm("mov r24,%1$rcall setBit"::"x"(X),"r"(B):"r24","r25");})

void DCF77Dec::ProcessVal(byte twobits) {
// Datenbit abspeichern, noch nicht auswerten
 byte b = recvbit;
 if (!(twobits&1)) setBit(&data,b);
 asm volatile(	// Bitnummer nichtlinear laufen lassen um spätere Vielbit-Verschiebungen zu vermeiden
"	cpi	%0,41	\n"	// hier (bei 41) hängen bleiben
"	breq	2f	\n"
"	inc	%0	\n"
"	sbrc	%0,6	\n"	// 64->40
"	 ldi	%0,40	\n"
"	cpi	%0,39	\n"	// 39->42
"	brne	1f	\n"
"	ldi	%0,42	\n"
"1:	cpi	%0,22	\n"	// 22->24
"	brne	1f	\n"
"	ldi	%0,24	\n"
"1:	cpi	%0,15	\n"	// 15->16
"	brne	2f	\n"
"	inc	%0	\n"
"2:			\n"
:"+d"(b));
 recvbit = b;
// Zeit aktualisieren
// Das passiert in Zehntelsekunde 5 also 0,5 s zu früh.
// Das ist wichtig und richtig weil die „Meldekette“ Zeit braucht.
// Gewünscht ist eine zehntelsekundengenaue Zeitanzeige.
 byte s=Second;
 if (s<99) ++s;
// Eine Resynchronisation mit einer Minutenmarke geht nur via Trust≡0.
// Bei vielen Fehlern: Trust in großen Schritten hochzählen und in kleinen 'runter.
 if (Trust) {
  byte sec=60;
  if (Trust>3 && data.inf&0x10 && data.min==59 && twobits!=3) ++sec;	// (positive) Schaltsekunde erwarten
  if (s==sec) {
   s=0;		// (ggf. synthetische) Minutemnarke
   if (twobits!=3 && !--Trust) {	// Minutenmarke muss kommen, sonst abwerten
    Second=0;
    return;	// raus bei Trust≡0
   }
  }else if (twobits==3 && !--Trust) {	// Minutenmarke darf nicht kommen, sonst abwerten
   Second=0;	// Bei Trust≡0 Sekundenzähler rücksetzen …
   return;	// … und keine Zeitauswertung
  }
 }else if (twobits==3) {Trust=1; s=0;}	// Sekunden fortlaufend, durchaus ≥ 60
// Minutenanfang setzen NUR wenn noch keine Minute erfolgreich empfangen wurde,
// d.h. Trust≡0. Sonst fehlende Trägerabsenkung nur „bestrafen“ und ignorieren.
 Second=s;
 if (s) return;	// Folgender Kode nur nach (ggf. synthetischer) Minutenmarke
 if (Trust>1) ++dt;
 DateTime dtl;
 unsigned Err = dtl=data;	// 12 verschiedene Fehlerbits
 Info = data.inf&0x1F;
 if (Err) /*uprintf(FP("Err=%X"),Err)*/;
 else{
  byte Mod = dt = dtl;
  if (Mod) {
//   uprintf(FP("Mod=%X"),Mod);
   if (Trust>1) Err|=1<<11;	// Das ist auch ein Fehler!
  }
 }
 if (Err && Trust>3) --Trust;	// Herabstufen (TODO: Parallele Quarzuhr)
 if (!Err && Trust<99) ++Trust;
 memset(&recvbit,0,9);
}

void DateTime::print() const{
 uprintf(F("%.2s, %02u.%02u.%u %02u:%02u"),
	F("SoMoDiMiDoFrSa") + 2*WDay,
	byte(Date+1),
	byte(Month+1),
	Year+2000,
	Hour&0x1F,
	Minute);
}
Detected encoding: UTF-80