CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DCF77 decoder

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
inservi



Joined: 13 May 2007
Posts: 128

View user's profile Send private message

DCF77 decoder
PostPosted: Sun Oct 07, 2007 10:55 am     Reply with quote

Hello, here is a simple DCF77 decoder with little sample.

-----------------------------------------------------------------------
UPDATE The October 08 2007 changing :
#define DCF77ValuesDayOfWeek 5 // ( 3 was a fault )
-----------------------------------------------------------------------
the October 12 2007
some little enhancement in DCF77Decoding.c
-----------------------------------------------------------------------
the October 14 2007
little correction in weekday
-----------------------------------------------------------------------
the October 18 2007
Improvement to the timer management.
Simple sample for how to make a zero drift timer with just some defines
and one set_Timer () at the start of interrupt.

1 - setup the timer for a time overflow a few bigger than the needed one
2 - type the parameters in the #defines as in this sample
3 - add the 'set_TimerX( DCF77SetTimer ); ' at the beginning of the interrupt

-----------------------------------------------------------------------
the june 19 2008
improvement for zero drift timer from ckielstra
-----------------------------------------------------------------------

Code:
////////////////////////////////////////////////////////////////////////////
//               DCF77 DECODER                                            //
//                                                                        //
//  Writen by Daniel ROBERT  V1.0    07 october 2007                      //
//                                                                        //
//                                                                        //
//  Although the radio transmission of DCF77 signal is not                //
//  highly reliable, it can be practical to use it for time               //
//  initialisation.                                                       //
//  It is appropriate then to manage the real houre progression           //
//  with an autonomous clock.                                             //
//                                                                        //
//  If receiver DCF77 is used to maintain the hour  continually,          //
//  it is necessary to check at each end of cycle ( each minute )         //
//  if the new hour is well corresponding to the previous one plus        //
//  one minute. In any way an autonomous (internal) clock is needed       //
//  to allows to maintain the hour right for several minute because       //
//  of some parasite can easily block the reception for a long time.      //
//                                                                        //
//  In some environments, it is difficult to get a right signal           //
//                                                                        //
//  Three led are used for monitoring the reception progress.             //
//    LED_Error  is lighting when radio error                             //
//    LED_ZERO   is flashing when a zero is received                      //
//    LED_ONE    is flashing when a ONE is received                       //
//                                                                        //
//    LED_ZERO and LED_ONE   are lighting together (1 sec) at             //
//                           the start of cycle                           //
//                                                                        //
//  For demo, the result is sended to hyperterminal in VT100 mode         //
//                                                                        //
//  At starting, nothink appens until the 'start' is received (that       //
//  can take almost one minute) Then the two data led are blinking        //
//  togther 1 seconde. After that, the led ONE and ZERO must blink        //
//  one at the time, until the end of cycle. In case of radio error,      //
//  the Error led start lighting until the next start. Then the cycle     //
//  is restarting.                                                        //
//                                                                        //
//  This code will easily work on most PIC with CCS C V 3.x and V 4.x     //
//                                                                        //
//  I'm working to changing 'int DCF77Bits[59]' array for use only        //
//  59 bits rather than 59 bytes.                                         //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

#include "18F2620.h"

#FUSES NOWDT                   //No Watch Dog Timer
#FUSES WDT128                  //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                      //High speed Osc (> 4mhz)
#FUSES NOPROTECT               //Code not protected from reading
#FUSES IESO                    //Internal External Switch Over mode enabled
#FUSES BROWNOUT                //Reset when brownout detected
#FUSES BORV21                  //Brownout reset at 2.1V
#FUSES PUT                     //Power Up Timer
#FUSES NOCPD                   //No EE protection
#FUSES STVREN                  //Stack full/underflow will cause reset
#FUSES NODEBUG                 //No Debug mode for ICD
#FUSES NOLVP                   //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                   //Program memory not write protected
#FUSES NOWRTD                  //Data EEPROM not write protected
#FUSES NOEBTR                  //Memory not protected from table reads
#FUSES NOCPB                   //No Boot Block code protection
#FUSES NOEBTRB                 //Boot block not protected from table reads
#FUSES NOWRTC                  //configuration not registers write protected
#FUSES NOWRTB                  //Boot block not write protected
#FUSES FCMEN                   //Fail-safe clock monitor enabled
//#FUSES XINST                   //Extended set extension and Indexed Addressing mode enabled
#FUSES NOPBADEN                //PORTB pins are configured as digital I/O on RESET
#FUSES LPT1OSC                 //Timer1 configured for low-power operation
#FUSES MCLR                    //Master Clear pin enabled

//------------------- FOR EASY ZERO DRIFT TIMER -------------------
#define FOSC                 20000000   // used for setup delay and calculate the zero drift timmer
#define DCF77TimerDepth      65536      // for 16 bit timer
#define DCF77TimerPrescaler  1          // for prescaler div by 1
//------------------- FOR EASY ZERO DRIFT TIMER -------------------
 
#use delay(clock=FOSC)


#define LCD_TX     PIN_C6
#define LCD_RX     PIN_C6
#define LCD_BAUD   4800

#define RADIO_PORT     PIN_C2   // input from DCF77 receiver
#define LED_Error      PIN_A2   // led indicating DCF77 error
#define LED_ZERO       PIN_A3   // led indicating a zero from DCF77
#define LED_ONE        PIN_A4   // led indicating a one from DCF77

#define RADIO_PORT_HIGH  input(RADIO_PORT)
#define RADIO_PORT_LOW  !input(RADIO_PORT)

#use RS232(baud=LCD_BAUD, xmit=LCD_TX , rcv=LCD_RX )

#define VT100LF      "%c[B", 27   // "%c%c",13,10
#define VT100CLS     "%c[2J", 27  //"%c",12
#define VT100HOME    "%c[H", 27

// --RTC--
#define RadioLength0         10    // not used - length of pulse for a zero
#define RadioLength1         15    // 150 ms minimum (normalement 160 minimum 200 tipicaly)
#define RadioLengthStart     100   // normaly, 1 sec then 100

#define RadioStartMinute     21    // position of first bit of minute in dcf77 scheme
#define RadioParityMinute    28    // same story for next element
#define RadioStartHeure      29    //    "
#define RadioParityHeure     35    //    "
#define RadioStartDay        36    //    "
#define RadioStartDayOfWeek  42    //    "
#define RadioStartMonth      45    //    "
#define RadioStartYear       50    //    "
#define RadioParity3         58    //    "

#define DCF77ValuesMinute     0    // element number is scheme
#define DCF77ValuesHour       2    // same story for next element
#define DCF77ValuesDay        4    //    "
#define DCF77ValuesDayOfWeek  5    //    "
#define DCF77ValuesMonth      6    //    "
#define DCF77ValuesYear       7    //    "

//------------------- FOR EASY ZERO DRIFT TIMER -------------------
#define DCF77InteruptTime    0.01   // sec
#define DCF77SetTimer        (int16)( DCF77TimerDepth * DCF77TimerPrescaler ) - (int16)( DCF77InteruptTime * (FOSC / 4) )
//------------------- FOR EASY ZERO DRIFT TIMER -------------------


// --------- GLOBAL DECLARATION --------------
int8       DCF77Bits[59] = {0} ;   // table for put all DCF77 bits for one cycle
int8 const DCF77BitWeight[8] = {1,2,4,8,10,20,40,80};
char const DOW[7][8] = { {"Mon\0"}, {"Tues\0"}, {"Wednes\0"}, {"Thurs\0"}, {"Fri\0"}, {"Satur\0"}, {"Sun\0"} } ;

                           // | 128 for set the bit 7  for indicate that it is a parity bit
int8 const DCF77Scheme[9]= { RadioStartMinute, RadioParityMinute | 128, RadioStartHeure, RadioParityHeure | 128,
                             RadioStartDay, RadioStartDayOfWeek, RadioStartMonth, RadioStartYear, RadioParity3 | 128 } ;                       
int8       DCF77Values[9] = {0} ;
int8       DCF77Sec ;
int8       DCF77LastDate = 0 ;
short      DCF77TimeOk = false, DCF77CycleOK = false ;
int8       LastRadioTime = 0 ;
int8       DCF77Pulse = 0 ;                // lenght of pulse is hundredth (sec/100) of Sec
short      RadioBit , RadioParity ;
int8       DCF77BitNbr = 0 ;
short      RadioWaitStart = true, RadioWaitHight, RadioHightMesure ;
int8       heure = 0, Minute = 0, Seconde = 0 ;
int8       day = 0, dayOfWeek = 0, month = 0, year = 0 ;
int8       Sec100 ;
short      SecondeFlag = 0, MinuteFlag = 0 ;
short      RadioError = false ;


#int_timer0
void timer0_isr() {
//------------------- FOR EASY ZERO DRIFT TIMER -------------------
  //set_Timer0( DCF77SetTimer );
  set_timer0( get_timer0() + DCF77SetTimer ) // enhancement from ckielstra
//------------------- FOR EASY ZERO DRIFT TIMER -------------------

  // -- autonomous clock --
  if (++Sec100 == 100) {
    Sec100 = 0 ;
    SecondeFlag = 1 ;
   
    if (++DCF77Sec == 60) DCF77Sec = 0 ; // count hundredth (1/100) of second  for DCF77
   
    if (++Seconde == 60) {            // hours
      Seconde = 0;
      MinuteFlag = 1;
      if (++Minute == 60) {           // hours
        Minute = 0 ;
        if (++heure == 24) heure = 0 ; // days
      }
    }
  }
  // --------------------
 
  if (++DCF77Pulse >= RadioLengthStart) {   //if low for at least 1 sec then start or error. Assume start
    RadioWaitStart = true ;
    RadioWaitHight = false ;
    RadioHightMesure = false ;
  }

  if (RadioWaitStart) { // wait for starting cycle. the length is at least 1 second
    if ( RADIO_PORT_HIGH ) {
      DCF77Pulse = 0 ; // reset if in high pulse ( after an error ) for mesure from start of zero     
    }
    if (DCF77Pulse >= RadioLengthStart) { // starting cycle
      RadioError = false ;
      output_high(LED_ZERO);   //
      output_high(LED_ONE);    // At start, the two led (one and zero) are blinking together
      DCF77Pulse =0 ;          // reset hundredth count
      RadioWaitStart = false ;
      RadioWaitHight = true ;  // past to next step wait for begin of hight pulse
      DCF77BitNbr = 0 ;
      DCF77Sec = 59 ;          // init secondes
      Sec100 = 30 ;

    }
  }

  if (RadioWaitHight) { // wait for start of hight pulse
    if ( RADIO_PORT_HIGH ) {
      DCF77Pulse = 0 ;
      RadioWaitHight = false ;
      RadioHightMesure = true ;
      output_low(LED_ZERO);
      output_low(LED_ONE);
    }
  }

  if (RadioHightMesure) {   // mesure the lengh of higth pulse
    if ( RADIO_PORT_LOW ) { // end of high pulse, now DCF77Pulse contain the length of high pulse
      RadioBit = (DCF77Pulse >= RadioLength1) ;   // if DCF77 high pulse is greater than 160mS is 1 else is 0
      if ( DCF77Pulse > 25 || DCF77Pulse < 8 ) {  // if DCF77 high pulse is greater than 210mS or smaller 90mS then error
        RadioError = true ;
        RadioWaitStart = true ;                   // restart the waiting for start pulse (no signal for 1 sec)
      }
     
      DCF77Pulse = 0 ;                            // reset counter for pulse length
      DCF77Bits[DCF77BitNbr] = RadioBit ;         // put bit into table

      if (++DCF77BitNbr == 59) {                  // if end of cycle
        RadioWaitStart = true ;
        DCF77CycleOK = true ;
      }
      RadioHightMesure = false ;
      RadioWaitHight = !RadioWaitStart  ;         // back to wait for next hight pulse if cycle not finished and no error
     
      // --- can be deleted --- juste for debugging
      output_bit(LED_ZERO, !RadioBit ) ;         
      output_bit(LED_ONE,   RadioBit ) ;
      // ----------------------

    }
  }
}

#include <calcDCF77.c>


void StartTimer() {
  Sec100 = 0 ;
  set_Timer0( DCF77SetTimer );
  enable_interrupts(INT_TIMER0);
}

void StopTimer() {
  DISABLE_INTERRUPTS(INT_TIMER0);
}

int DCF77DateInt() { 
  return(DCF77Values[DCF77ValuesDay]+DCF77Values[DCF77ValuesMonth]+DCF77Values[DCF77ValuesYear]);
}

void fAffTime() {
  output_bit(LED_Error, RadioError);
  printf("\r");
  printf("%2u:%02u:%02u ", Heure , Minute, Seconde );
}

void fAffDate() {
    printf("\n\r");  // next line
    printf( "%s", DOW[dayOfWeek-1] );
    printf(" %02u/%02u/%02u",  day,  month,  year  );
    DCF77LastDate = DCF77DateInt();
   
    printf(VT100HOME); // home
}


void main() {

  // --INIT RTC--
  setup_wdt(WDT_OFF);
  setup_timer_0( RTCC_INTERNAL | RTCC_DIV_1 ); // 13.1 mS
  setup_timer_1(T1_DISABLED);
  setup_timer_2(T2_DISABLED,0,1);
  // ------------

  setup_adc_ports(NO_ANALOGS);

  delay_ms(100) ;

  printf(VT100CLS) ;
  printf("DCF77 Clock(c)IS");
  delay_ms(1000);

  // initialise time for test
  Heure = 10;
  Minute = 26 ;
  Seconde = 0 ;

  enable_interrupts(GLOBAL);
  StartTimer() ;
 
  printf(VT100CLS);  // Clear screen

  while (true) {   

    if ( DCF77CycleOK ) {      // a complete cycles  is finished

      DCF77Decoding( DCF77ValuesMinute, DCF77ValuesYear );  // it is possible to ask decoding of a part of received data
                                                            // after testing of DCF77BitNbr
                                                            // if DCF77BitNbr is >= DCF77ValuesDay then you
                                                            // can already decode minutes and hours
                                                           
      DCF77CycleOK = false ;   // for decoding DCF77 only one time when a cycle is finished

      if ( DCF77TimeOk ) {     // if no parity errors
        DCF77TimeOk = false ;

        Seconde =   DCF77Sec ;
        Minute =    DCF77Values[DCF77ValuesMinute] ;
        Heure =     DCF77Values[DCF77ValuesHour] ;
        day =       DCF77Values[DCF77ValuesDay] ;
        dayOfWeek = DCF77Values[DCF77ValuesDayOfWeek] ;
        month =     DCF77Values[DCF77ValuesMonth] ;
        year  =     DCF77Values[DCF77ValuesYear] ;

        if ( DCF77LastDate != DCF77DateInt() ) fAffDate() ;  //
       
      }
    }

    if ( SecondeFlag ) {  // refresh time each seconds
      fAffTime();
      SecondeFlag = 0;
    }

  }

}


And calcDCF77.c
Code:

void DCF77Decoding( int first, int last ) {
 int i,j, DCF77BitWeightSubscr ;
 int calcStart, calcEnd ;
 short parityTest ;

  RadioError = false ;

  for( j=first; j <= last; j++ ) {
    DCF77Values[j] = 0 ;
    calcStart = DCF77Scheme[j] ;
    calcEnd   = DCF77Scheme[j+1] ;

    parityTest = bit_test( calcEnd, 7 ) ;
    bit_clear(calcEnd, 7 );
   
    DCF77BitWeightSubscr = 0 ;
    for( i=calcStart; i < calcEnd; i++ ) {
      if ( DCF77Bits[i] ) {
        DCF77Values[j] += DCF77BitWeight[DCF77BitWeightSubscr] ;
        RadioParity = !RadioParity ;
      }
      ++DCF77BitWeightSubscr ;
    }
   
    if ( parityTest ) {
      RadioError = ( RadioParity != DCF77Bits[calcEnd] ) ;
      RadioParity = 0 ;
      j++ ;
    }
    if ( RadioError ) break ;
  }
 
 
  // -- The  autonomous clock  will add a minute because second is just set at 0 then minute - 1 ---
  //    not necessary without autonomous clock
  if ( !RadioError ) { 
    if (!DCF77Values[DCF77ValuesMinute]--) {
      DCF77Values[DCF77ValuesMinute] = 59;
      if(!DCF77Values[DCF77ValuesHour]--) DCF77Values[DCF77ValuesHour] = 23 ;
    }
  }
  // --------------------------------------------------------------------------------------
 
  DCF77TimeOk = !RadioError ;

}



Your commentary and/or suggestions are welcome.

dro.
_________________
in médio virtus


Last edited by inservi on Mon May 19, 2008 4:14 am; edited 8 times in total
inservi



Joined: 13 May 2007
Posts: 128

View user's profile Send private message

PostPosted: Mon Oct 08, 2007 3:31 am     Reply with quote

Hello,

The version with data stocked in bit is there ! (Is about less than 50 bytes of data saved).


--------------------------------------
little enhancement
Update the October 11 2007
removing 'day' from element to char const DOW and add one time in printf
--------------------------------------
--------------------------------------
BIG ERROR CORRECTING
the October 12 2007
added bit_clear(DCF77Bits[DCF77ByteNbr],DCF77BitNbr);
before DCF77Bits[DCF77ByteNbr] |= RadioBit<<DCF77BitNbr ;

some little enhancement in DCF77Decoding.c
--------------------------------------
the October 14 2007
little correction in weekday
--------------------------------------

-----------------------------------------------------------------------
the june 19 2008
improvement for zero drift timer from ckielstra
-----------------------------------------------------------------------

Code:
////////////////////////////////////////////////////////////////////////////
//               DCF77 DECODER                                            //
//                                                                        //
//  Writen by Daniel ROBERT  V1.1    08 october 2007                      //
//                                                                        //
//                                                                        //
//  Although the radio transmission of DCF77 signal is not                //
//  highly reliable, it can be practical to use it for time               //
//  initialisation.                                                       //
//  It is appropriate then to manage the real houre progression           //
//  with an autonomous clock.                                             //
//                                                                        //
//  If receiver DCF77 is used to maintain the hour  continually,          //
//  it is necessary to check at each end of cycle ( each minute )         //
//  if the new hour is well corresponding to the previous one plus        //
//  one minute. In any way an autonomous (internal) clock is needed       //
//  to allows to maintain the hour right for several minute because       //
//  of some parasite can easily block the reception for a long time.      //
//                                                                        //
//  In some environments, it is difficult to get a right signal           //
//                                                                        //
//  Three led are used for monitoring the reception progress.             //
//    LED_Error  is lighting when radio error                             //
//    LED_ZERO   is flashing when a zero is received                      //
//    LED_ONE    is flashing when a ONE is received                       //
//                                                                        //
//    LED_ZERO and LED_ONE   are lighting together (1 sec) at             //
//                           the start of cycle                           //
//                                                                        //
//  For demo, the result is sended to hyperterminal in VT100 mode         //
//                                                                        //
//  At starting, nothink appens until the 'start' is received (that       //
//  can take almost one minute) Then the two data led are blinking        //
//  togther 1 seconde. After that, the led ONE and ZERO must blink        //
//  one at the time, until the end of cycle. In case of radio error,      //
//  the Error led start lighting until the next start. Then the cycle     //
//  is restarting.                                                        //
//                                                                        //
//  This code will easily work on most PIC with CCS C V 3.x and V 4.x     //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

#include "18F2620.h"

#FUSES NOWDT                   //No Watch Dog Timer
#FUSES WDT128                  //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                      //High speed Osc (> 4mhz)
#FUSES NOPROTECT               //Code not protected from reading
#FUSES IESO                    //Internal External Switch Over mode enabled
#FUSES BROWNOUT                //Reset when brownout detected
#FUSES BORV21                  //Brownout reset at 2.1V
#FUSES PUT                     //Power Up Timer
#FUSES NOCPD                   //No EE protection
#FUSES STVREN                  //Stack full/underflow will cause reset
#FUSES NODEBUG                 //No Debug mode for ICD
#FUSES NOLVP                   //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                   //Program memory not write protected
#FUSES NOWRTD                  //Data EEPROM not write protected
#FUSES NOEBTR                  //Memory not protected from table reads
#FUSES NOCPB                   //No Boot Block code protection
#FUSES NOEBTRB                 //Boot block not protected from table reads
#FUSES NOWRTC                  //configuration not registers write protected
#FUSES NOWRTB                  //Boot block not write protected
#FUSES FCMEN                   //Fail-safe clock monitor enabled
//#FUSES XINST                   //Extended set extension and Indexed Addressing mode enabled
#FUSES NOPBADEN                //PORTB pins are configured as digital I/O on RESET
#FUSES LPT1OSC                 //Timer1 configured for low-power operation
#FUSES MCLR                    //Master Clear pin enabled

//------------------- FOR EASY ZERO DRIFT TIMER -------------------
#define FOSC                 20000000   // used for setup delay and calculate the zero drift timmer
#define DCF77TimerDepth      65536      // for 16 bit timer
#define DCF77TimerPrescaler  1          // for prescaler div by 1
//------------------- FOR EASY ZERO DRIFT TIMER -------------------
 
#use delay(clock=FOSC)



#define LCD_TX     PIN_C6
#define LCD_RX     PIN_C6
#define LCD_BAUD   4800

#define RADIO_PORT     PIN_C2   // input from DCF77 receiver
#define LED_Error      PIN_A2   // led indicating DCF77 error
#define LED_ZERO       PIN_A3   // led indicating a zero from DCF77
#define LED_ONE        PIN_A4   // led indicating a one from DCF77

#define RADIO_PORT_HIGH  input(RADIO_PORT)
#define RADIO_PORT_LOW  !input(RADIO_PORT)

#use RS232(baud=LCD_BAUD, xmit=LCD_TX , rcv=LCD_RX )

#define VT100LF      "%c[B", 27   // "%c%c",13,10
#define VT100CLS     "%c[2J", 27  //"%c",12
#define VT100HOME    "%c[H", 27

// --RTC--
#define RadioLength0         10    // not used - length of pulse for a zero
#define RadioLength1         15    // 150 ms minimum (normalement 160 minimum 200 tipicaly)
#define RadioLengthStart     100   // normaly, 1 sec then 100

#define RadioStartMinute     21    // position of first bit of minute in dcf77 scheme
#define RadioParityMinute    28    // same story for next element
#define RadioStartHeure      29    //    "
#define RadioParityHeure     35    //    "
#define RadioStartDay        36    //    "
#define RadioStartDayOfWeek  42    //    "
#define RadioStartMonth      45    //    "
#define RadioStartYear       50    //    "
#define RadioParity3         58    //    "

#define DCF77ValuesMinute     0    // element number is scheme
#define DCF77ValuesHour       2    // same story for next element
#define DCF77ValuesDay        4    //    "
#define DCF77ValuesDayOfWeek  5    //    "
#define DCF77ValuesMonth      6    //    "
#define DCF77ValuesYear       7    //    "

//------------------- FOR EASY ZERO DRIFT TIMER -------------------
#define DCF77InteruptTime    0.01   // sec
#define DCF77SetTimer   (int16)( DCF77TimerDepth * DCF77TimerPrescaler ) - (int16)( DCF77InteruptTime * (FOSC / 4) )
//------------------- FOR EASY ZERO DRIFT TIMER -------------------

// --------- GLOBAL DECLARATION --------------
int8       DCF77Bits[9] = {0} ;   // table for put all DCF77 bits for one cycle
int8 const DCF77BitWeight[8] = {1,2,4,8,10,20,40,80};
char const DOW[7][8] = { {"Mon\0"}, {"Tues\0"}, {"Wednes\0"}, {"Thurs\0"}, {"Fri\0"}, {"Satur\0"}, {"Sun\0"} } ;

                           // | 128 for set the bit 7  for indicate that it is a parity bit
int8 const DCF77Scheme[9]= { RadioStartMinute, RadioParityMinute | 128, RadioStartHeure, RadioParityHeure | 128,
                             RadioStartDay, RadioStartDayOfWeek, RadioStartMonth, RadioStartYear, RadioParity3 | 128 } ;                       
                             
int8       DCF77Values[9] = {0} ;
int8       DCF77Sec ;
int8       DCF77LastDate = 0 ;
short      DCF77TimeOk = false, DCF77CycleOK = false ;
int8       LastRadioTime = 0 ;
int8       DCF77Pulse = 0 ;                // lenght of pulse is hundredth (sec/100) of Sec
short      RadioBit , RadioParity ;
int8       DCF77BitNbr = 0, DCF77ByteNbr = 0 ;
short      RadioWaitStart = true, RadioWaitHight, RadioHightMesure ;
int8       heure = 0, Minute = 0, Seconde = 0 ;
int8       day = 0, dayOfWeek = 0, month = 0, year = 0 ;
int8       Sec100 ;
short      SecondeFlag = 0, MinuteFlag = 0 ;
short      RadioError = false ;


#int_timer0
void timer0_isr() {
//------------------- FOR EASY ZERO DRIFT TIMER -------------------
  set_Timer0( get_timer0() + DCF77SetTimer ); // for exactly 100 mSec
//------------------- FOR EASY ZERO DRIFT TIMER -------------------

  // -- autonomous clock --
  if (++Sec100 == 100) {
    Sec100 = 0 ;
    SecondeFlag = 1 ;
   
    if (++DCF77Sec == 60) DCF77Sec = 0 ; // count hundredth (1/100) of second  for DCF77
   
    if (++Seconde == 60) {            // hours
      Seconde = 0;
      MinuteFlag = 1;
      if (++Minute == 60) {           // hours
        Minute = 0 ;
        if (++heure == 24) heure = 0 ; // days
      }
    }
  }
  // --------------------

  if (++DCF77Pulse >= RadioLengthStart) {   //if low for at least 1 sec then start or error. Assume start
    RadioWaitStart = true ;
    RadioWaitHight = false ;
    RadioHightMesure = false ;
  }

  if (RadioWaitStart) { // wait for starting cycle. the length is at least 1 second
    if ( RADIO_PORT_HIGH ) {
      DCF77Pulse = 0 ; // reset if in high pulse ( after an error ) for mesure from start of zero     
    }
    if (DCF77Pulse >= RadioLengthStart) { // starting cycle
      RadioError = false ;
      output_high(LED_ZERO);   //
      output_high(LED_ONE);    // At start, the two led (one and zero) are blinking together
      DCF77Pulse =0 ;          // reset hundredth count
      RadioWaitStart = false ;
      RadioWaitHight = true ;  // past to next step wait for begin of hight pulse
      DCF77ByteNbr = 0 ;
      DCF77BitNbr = 0 ;
      DCF77Sec = 59 ;          // init secondes
    }
  }

  if (RadioWaitHight) { // wait for start of hight pulse
    if ( RADIO_PORT_HIGH ) {
      DCF77Pulse = 0 ;
      RadioWaitHight = false ;
      RadioHightMesure = true ;
      output_low(LED_ZERO);
      output_low(LED_ONE);
    }
  }

  if (RadioHightMesure) {   // mesure the lengh of higth pulse
    if ( RADIO_PORT_LOW ) { // end of high pulse, now DCF77Pulse contain the length of high pulse
      RadioBit = (DCF77Pulse >= RadioLength1) ;   // if DCF77 high pulse is greater than 160mS is 1 else is 0
      if ( DCF77Pulse > 25 || DCF77Pulse < 8 ) {  // if DCF77 high pulse is greater than 210mS or smaller 90mS then error
        RadioError = true ;
        RadioWaitStart = true ;                   // restart the waiting for start pulse (no signal for 1 sec)
      }

      DCF77Pulse = 0 ;                            // reset counter for pulse length
      bit_clear(DCF77Bits[DCF77ByteNbr],DCF77BitNbr); 
      DCF77Bits[DCF77ByteNbr] |= RadioBit<<DCF77BitNbr ;         // put bit into table

      if (++DCF77BitNbr == 8) {
        DCF77BitNbr = 0 ;
        ++DCF77ByteNbr ;
      }
      if (DCF77ByteNbr == 7 && DCF77BitNbr == 3) {  // if end of cycle (7*8) + 3 = 59
        RadioWaitStart = true ;
        DCF77CycleOK = true ;
      }
      RadioHightMesure = false ;
      RadioWaitHight = !RadioWaitStart  ;         // back to wait for next hight pulse if cycle not finished and no error

      // --- can be deleted --- juste for monitoring
      output_bit(LED_ZERO, !RadioBit ) ;         
      output_bit(LED_ONE,   RadioBit ) ;
      // ----------------------

    }
  }
}

#include <calcDCF77-8.c>


void StartTimer() {
  Sec100 = 0 ;
  set_Timer0( DCF77SetTimer );
  enable_interrupts(INT_TIMER0);
}

void StopTimer() {
  DISABLE_INTERRUPTS(INT_TIMER0);
}

int DCF77DateInt() { 
  return(DCF77Values[DCF77ValuesDay]+DCF77Values[DCF77ValuesMonth]+DCF77Values[DCF77ValuesYear]);
}

void fAffTime() {
  output_bit(LED_Error, RadioError);
  printf("\r");
  printf("%2u:%02u:%02u ", Heure , Minute, Seconde );
}

void fAffDate() {
    printf("\n\r");  // next line
    printf( "%sday", DOW[dayOfWeek-1] );
    printf(" %02u/%02u/%02u",  day,  month,  year  );
    DCF77LastDate = DCF77DateInt();
   
    printf(VT100HOME); // home
}


void main() {

  // --INIT RTC--
  set_timer0(0) ;
  setup_timer_0(RTCC_INTERNAL);
  setup_timer_2(T2_DIV_BY_16,196,16);
  // ------------

  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_CLOCK_DIV_2);
  setup_spi(FALSE);
  setup_timer_1(T1_DISABLED);
  setup_ccp1(CCP_OFF);
  setup_ccp2(CCP_OFF);

  delay_ms(100) ;


  printf(VT100CLS) ;
  printf("DCF77 Clock(c)IS");
  delay_ms(1000);

  // initialise time for test
  Heure = 10;
  Minute = 26 ;
  Seconde = 0 ;

  enable_interrupts(GLOBAL);
  StartTimer() ;
 
  printf(VT100CLS);  // Clear screen

  while (true) {   

    if ( DCF77CycleOK ) {      // a complete cycles  is finished

      DCF77Decoding( DCF77ValuesMinute, DCF77ValuesYear );  // it is possible to ask decoding of a part of received data
                                                            // after testing of DCF77BitNbr
                                                            // if DCF77BitNbr is >= DCF77ValuesDay then you
                                                            // can already decode minutes and hours
                                                           
      DCF77CycleOK = false ;   // for decoding DCF77 only one time when a cycle is finished

      if ( DCF77TimeOk ) {     // if no parity errors
        DCF77TimeOk = false ;

        Seconde =   DCF77Sec ;
        Minute =    DCF77Values[DCF77ValuesMinute] ;
        Heure =     DCF77Values[DCF77ValuesHour] ;
        day =       DCF77Values[DCF77ValuesDay] ;
        dayOfWeek = DCF77Values[DCF77ValuesDayOfWeek] ;
        month =     DCF77Values[DCF77ValuesMonth] ;
        year  =     DCF77Values[DCF77ValuesYear] ;

        if ( DCF77LastDate != DCF77DateInt() ) fAffDate() ;  //
       
      }
    }

    if ( SecondeFlag ) {  // refresh time each seconds
      fAffTime();
      SecondeFlag = 0;
    }

  }

}


And the calcDCF77-8.c
Code:
void calcIndices(int8 indice, int8 *ByteNbr, int8 *BitNbr) {
  *ByteNbr= indice / 8 ;
  *BitNbr = indice - ( *ByteNbr * 8 ) ;
}

void DCF77Decoding( int first, int last ) {
 int8   i,j, DCF77BitWeightSubscr ;
 int8   calcStart, calcEnd ;
 short  parityTest ;
 int8   ByteNbr, BitNbr ;

  RadioParity = 0 ;
  RadioError = false ;

  for( j=first; j <= last; j++ ) {
    DCF77Values[j] = 0 ;
    calcStart = DCF77Scheme[j] ;
    calcEnd   = DCF77Scheme[j+1] ;

     parityTest = bit_test( calcEnd, 7 ) ;
     bit_clear(calcEnd, 7 );

    DCF77BitWeightSubscr = 0 ;
    for( i=calcStart; i < calcEnd; i++ ) {
      calcIndices( i, &ByteNbr, &BitNbr ) ;
      if ( bit_test( DCF77Bits[ByteNbr], BitNbr ) ) {
        DCF77Values[j] += DCF77BitWeight[DCF77BitWeightSubscr] ;
        RadioParity = !RadioParity ;
      }
      ++DCF77BitWeightSubscr ;
    }

    if ( parityTest ) {
      calcIndices( calcEnd, &ByteNbr, &BitNbr ) ;
      RadioError = ( RadioParity != bit_test( DCF77Bits[ByteNbr], BitNbr ) ) ;
      RadioParity = 0 ;
      j++ ;
    }
    if ( RadioError ) break ;
  }

  // -- The  autonomous clock  will add a minute because second is just set at 0 then minute - 1 ---
  //    not necessary without autonomous clock
  if ( !RadioError ) { 
    if (!DCF77Values[DCF77ValuesMinute]--) {
      DCF77Values[DCF77ValuesMinute] = 59;
      if(!DCF77Values[DCF77ValuesHour]--) DCF77Values[DCF77ValuesHour] = 23 ;
    }
  }
  // --------------------------------------------------------------------------------------

  DCF77TimeOk = !RadioError ;

}



dro.
_________________
in médio virtus
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group