Binäre DCF77 Uhr mit exponentiellem Filter und Blinkenlighty

Hier das Testprogramm zum vorherigen Beitrag:

/************************************************************************* 
 Testprogramm zum Testen von DCF-Modulen und DCF-Softwarefiltern
 
 Es können entweder zwei DCF-Module gegeneinander getestet werden
 Dazu die zwei Dateneingänge mit den Pins DCF_A_MODULE und DCF_B_MODULE verbinden
 und die Zeile "#define B_IS_FILTERED_A" auskommentieren
 
 Oder es kann ein DCF-Modul gegen einen Softwarefilter getestet werden
 Beispielhaft ist der hier vorgestellte Filter eingebaut:
 http://arduino.cc/forum/index.php?topic=135153.0
 Dazu das DCF-Modul an den Pin DCF_A_MODULE anschliessen und
 die Zeile "#define B_IS_FILTERED_A" in den Code einfügen
 (Der Pin DCF_B_MODULE bleibt dann frei.)
  
**************************************************************************/

// Pin fuer DATA-Ausgang des DCF-Moduls
#define DCF_A_MODULE 2

// Pin fuer DATA-Ausgang des zweiten DCF-Moduls oder den Software-Filter
#define DCF_B_MODULE 3

// die nachfolgende Zeile auskommentieren, wenn zwei Module getestet werden sollen
#define B_IS_FILTERED_A
// (wenn "#define B_IS_FILTERED_A" gesetzt ist, den Pin für das DCF_B_MODULE freilassen!)

// legt fest, an welchem Pin eine LED blinken soll
#define LED 13

#ifdef B_IS_FILTERED_A
  #include <MsTimer2.h>
#endif

char error[]="SYNC";
char noerror[]="";

void setup() {
  Serial.begin(9600);
  Serial.println();
  pinMode(DCF_A_MODULE, INPUT);
  pinMode(DCF_B_MODULE, INPUT);
  pinMode(LED, OUTPUT);
#ifdef B_IS_FILTERED_A
  pinMode(DCF_B_MODULE, OUTPUT);
  MsTimer2::set(1, low_pass_filter);
  MsTimer2::start();
#endif
}

#ifdef B_IS_FILTERED_A
void low_pass_filter() {
    // http://en.wikipedia.org/wiki/Low-pass_filter#Continuous-time_low-pass_filters
    // I will use fixed point arithmetics with 5 decimals
    const uint16_t decimal_offset = 10000;
    static uint32_t smoothed = 0*decimal_offset;
    const uint32_t input = digitalRead(DCF_A_MODULE) * decimal_offset;
//    const uint32_t input = analogRead(dcf77_analog_sample_pin)>200? decimal_offset: 0;
    // compute N such that the smoothed signal will always reach 50% of
    // the input after at most 50 samples (=50ms).
    // N = 1 / (1- 2^-(1/50)) = 72.635907286
    const uint16_t N = 72;
    smoothed = ((N-1) * smoothed + input) / N;
    // introduce some hysteresis
    static uint8_t square_wave_output = 0;
    if ((square_wave_output == 0) == (smoothed >= decimal_offset/2)) {
        // smoothed value more >= 50% away from output
        // ==> switch output
        square_wave_output = 1-square_wave_output;
        // ==> max the smoothed value in order to introduce some
        //     hysteresis, this also ensures that there is no
        //     "infinite memory"
        smoothed = square_wave_output? decimal_offset: 0;
      digitalWrite(DCF_B_MODULE, square_wave_output);   //changed jurs
    }
}
#endif


boolean 
  BdcfState,AdcfState,
  lastBdcfState=false,
  lastAdcfState=false;

byte
  AdcfBitval,BdcfBitval;

long 
  looptime,
  lastAdcfH,lastAdcfL,
  lastBdcfH,lastBdcfL,
  AdcfShortPulses,BdcfShortPulses,
  AdcfLastPulse,BdcfLastPulse,
  AdcfHighcycle, BdcfHighcycle;

void loop() {
//  looptime=millis()%100000L; // last 5 digits
  looptime=millis();
  AdcfState=digitalRead(DCF_A_MODULE);
  BdcfState=digitalRead(DCF_B_MODULE);
  digitalWrite(LED,BdcfState);
  CheckForHighCycle(looptime, AdcfState, lastAdcfState, AdcfHighcycle, lastAdcfH, lastAdcfL, AdcfShortPulses);
  CheckForHighCycle(looptime, BdcfState, lastBdcfState, BdcfHighcycle, lastBdcfH, lastBdcfL, BdcfShortPulses);
  printIfValidPulse('A', looptime, AdcfHighcycle, AdcfLastPulse, AdcfShortPulses, AdcfBitval, BdcfBitval, BdcfLastPulse);
  printIfValidPulse('B', looptime, BdcfHighcycle, BdcfLastPulse, BdcfShortPulses, BdcfBitval, AdcfBitval, AdcfLastPulse);
}

void printIfValidPulse(char c, long ltime, long &Highcycle, long &LastPulse, long &ShortPulses, byte &Bitval, byte OtherBitval, long LastOtherPulse)
{
  char *msg;
  char bitError;
  char buf[32];
  if ((Highcycle>=50)&&(Highcycle<=250))
  {
   // Falls mehr als 1500 ms kein Impuls ==> SYNC (Minutenimpuls oder Sync-Error) 
   if (looptime>LastPulse+1500) msg=error; else msg=noerror;
   // > 150 ms HIGH => 1-Bit, 50...150 ms HIGH => 0-Bit
   if (Highcycle>150) Bitval=1; else Bitval=0;
   // Biterror falls innerhalb der letzten 500 ms ein anderes Bit am anderen Eingang gemeldet wurde
   bitError=' ';
   // Biterror erkennen, falls weniger als 500 ms vorher ein anderes Bit am anderen Eingang erkannt wurde
   if ((looptime<LastOtherPulse+500)&&(Bitval!=OtherBitval)) bitError='*';
   // Biterror erkennen, falls der letzte Pulse vom selben Eingang kam
   if (LastPulse>LastOtherPulse) bitError='#';

   LastPulse=looptime;
   sprintf(buf,"%c %d %3ld %3ld %05ld%c%s", c, Bitval, Highcycle, ShortPulses,looptime%100000L,bitError,msg);
   Serial.println(buf);
   Highcycle=0;
   ShortPulses=0;
 }
}

void CheckForHighCycle(long looptime, boolean &State, boolean &lastState, long &Highcycle, long &lastH, long &lastL, long &ShortPulses)
{
  if (State!=lastState)
  {
    if (State==LOW)
    {
      Highcycle=looptime-lastH;
      if (Highcycle<50) ShortPulses++;
      lastL=looptime; 
    }
    else lastH=looptime;
    lastState=State;
  }
}