Source file: /~heha/basteln/PC/FunkUsb/FunkUsb.zip/FunkUsb/ve/DCF77.c

#include <string.h>
#include <util/parity.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

#include "FunkUsb.h"

struct clocktime n;
struct frame frame;

/*
static void incdate(struct clocktime*t) {};

static void inctime(struct clocktime*t) {
 if (++t->sec==60) {
  t->sec=0;
  if (++t->min==60) {
   t->min=0;
   if (++t->hour==24) {
    t->hour=0;
    incdate(t);
   }
  }
 }
}
*/

static BYTE bcd2bin(BYTE b) {
 return (b>>4)*10 + (b&0x0F);
}

/***********************************
 * Taktfrequenz der CPU umschalten *
 ***********************************/
void CpuSlow(void) {
 if (CLKPR&8) return;	// Ist schon langsam
 cli();
 CLKPR=0x80;
 CLKPR=0x08;		// /256, 64 kHz Taktfrequenz, reicht zum Zeit messen
 TCNT0=GPIOR1;		// Nachteiler herausnehmen
 sei();			// TODO: ADU
}

void CpuFast(void) {
 if (!CLKPR&8) return;	// Schon schnell
 cli();
 CLKPR=0x80;
 CLKPR=0x00;		// 16,5 MHz, für USB und rechenintensive Operationen
 GPIOR1=TCNT0;		// Nachteiler einschieben
 sei();			// TODO: ADU
}

static void Vergleich(void) {
 char m=TimeReport.t.min;
 char h=TimeReport.t.hour;
 BYTE d=ZoneMJD(&TimeReport.t);
 if (++m==60) {
  m=0; if (++h==24) d++;
 }
 StatusReport.someBits&=~4;
 if (m==n.min && h==n.hour && d==ZoneMJD(&n)) StatusReport.someBits|=4;
}

static WORD limits[3];
static unsigned long long *pData, *pOkay;

void dcf77Poll(void) {

 if (GPIOR0&0x08) {
  GPIOR0&=~0x08;
  PRR=0x0A;		// ADC aktivieren
  ADMUX = 0x90 | (ANA_BIT==5?0:ANA_BIT==2?1:ANA_BIT==4?2:3);
  ADCSRA = CLKPR&8 ? 0xD8 : 0xDF;
 }
 if (GPIOR0&0x04) {	// Flanke erkannt, Zeitstempel (8kHz) in T0Capture
#if 0
  WORD diff = T0Capture-lastStart;
  if (JoyReport.joyKey) {	// Beginn "ganze" Sekunde
   if (diff > (WORD)(1.5*F_TMR)) {	// Minutenlücke?
    n.sec=0;
    memset(&frame,0,sizeof(frame));
    BYTE minu=HistoryReport.nMinu;
    if (minu&0x0F<10) minu++;
    minu+=0x10; if ((minu&0xF0)==0xA0) minu&=0x0F;	// sollte 0x0A ergeben
    HistoryReport.nMinu=minu;
    pData=&HistoryReport.Data[minu>>4];
    memset(pData,0xFF,8);
    pOkay=&HistoryReport.Okay[minu>>4];
    memset(pOkay,0,8);
    Vergleich();
    TimeReport.t=n;	// müsste memcpy() kompilieren
   }else{
    if (n.sec<63) n.sec++;
   }
   lastStart = T0Capture;
  }else{
   unsigned hist_index=diff/(F_TMR/100);	// ungefähr
   if (hist_index>=50) hist_index=49;
   if (~HistoryReport.histo[hist_index]) HistoryReport.histo[hist_index]++;
   if (limits[0]<=diff && diff<=limits[2]) {
    ToggleBit(pOkay,n.sec);
    if (diff<limits[1]) {
     GPIOR0&=0x04;		// kurzer Impuls
     ToggleBit(pData,n.sec);
    }
   }else{
    ToggleBit(pData,n.sec);
   }
#if 0   
	
    if (sync && !frame.bitno)	{ // wenn neue Zeit empfangen wurde und 1. Bit nach Syncpause (= Start)
     timer0_cnt = 0;		// interner Timer auf Anfang			
					// weitere Prüfung eingebaut
     if (n.hour<24 && n.min<60 && (BYTE)(n.day-1)<31 && (BYTE)(n.month-1)<12) {
      if (comp_count == 1){  // empfangene Werte erstmal in Buffer "vgl"
       vgl = n;
       vgl.sec = 0; 		
      }
      if (comp_count==2) { // neu empfangene Werte mit Buffer "vgl" vergleichen
       if (!memcmp(&vgl.min,&n.min,6)) {
        cur = n;
	cur.sec = 0; 		// empfangene Uhrzeit für Anzeige übernehmen
	send_count ++;
	if (send_count == 100) send_count = 1;				
	sig_available = 99;		// Signalgüte hochsetzen
       }
       comp_count = 0;				// neues Spiel egal ob eingelesen oder nicht      
      }						
      comp_count++; // nach neuer Runde jetzt: (comp_count = 2)
     }							
     sync = 0;
    }			
   }
   LED_Port &= ~(1 << LED_Pin);	// LED aus
   timer1_stop ();			// liefert Impulsmesswert in µs
			// 150 ms
			
#endif
   if (GPIOR0&0x04) ToggleBit(&frame.data,frame.bitno);
   frame.bitno++;
   switch (frame.bitno) {
    case 16: {
     if (TimeReport.t.min==0) GrabWetter0(&frame);
     else if (TimeReport.t.min==2) GrabWetter2(&frame);
    }break;
    case 21: frame.bitno=24; break;
    case 39: frame.bitno=40; break;
    case 46: frame.bitno=48; break;
    case 51: frame.bitno=56; break;
    case 61: frame.bitno=64; break;
    case 73: {
     if (frame.wl&0x01
     || ((frame.tz&0x16)!=0x12 && (frame.tz&0x16)!=0x14)
     || parity_even_bit(frame.min)
     || parity_even_bit(frame.hour)
     || parity_even_bit(frame.day ^ frame.wday ^ frame.month ^ frame.year ^ frame.dpar)) {

     }else{	// Empfangene Zeit gültig => Interne Zeit setzen
      n.tz = frame.tz>>1&1;
      n.min = bcd2bin(frame.min&0x7F);
      n.hour = bcd2bin(frame.hour&0x3F);
      n.day = bcd2bin(frame.day);
      n.wday = frame.wday;
      n.month = bcd2bin(frame.month);
      n.year = bcd2bin(frame.year);
      if (TimeReport.t.min==1) GrabWetter1(&frame);
     }
    }break;
    case 74: frame.bitno=73; break;
   }
  }
#endif
  GPIOR0&=0x04;
 }
}
Detected encoding: UTF-80