gpio_set_mode(GPIO(RTC_DCF77_ENABLE_PORT),GPIO_MODE_OUTPUT_2_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(RTC_DCF77_ENABLE_PIN));// set pin to output push-pull to be able to enable the module
rcc_periph_clock_enable(RCC_TIM(RTC_DCF77_TIMER));// enable clock for timer peripheral
timer_reset(TIM(RTC_DCF77_TIMER));// reset timer state
timer_set_mode(TIM(RTC_DCF77_TIMER),TIM_CR1_CKD_CK_INT,TIM_CR1_CMS_EDGE,TIM_CR1_DIR_UP);// set timer mode, use undivided timer clock, edge alignment (simple count), and count up
timer_set_prescaler(TIM(RTC_DCF77_TIMER),1);// set prescaler to divide frequency by two, to be able to have a period of 1 kHz (72MHz/2/2^16=549Hz<1kHz)
timer_set_period(TIM(RTC_DCF77_TIMER),rcc_ahb_frequency/2/1000-1);// set period to 1kHz (plus hand tuning)
timer_clear_flag(TIM(RTC_DCF77_TIMER),TIM_SR_UIF);// clear update event flag
timer_update_on_overflow(TIM(RTC_DCF77_TIMER));// only use counter overflow as UEV source
timer_enable_irq(TIM(RTC_DCF77_TIMER),TIM_DIER_UIE);// enable update interrupt for timer
nvic_enable_irq(NVIC_TIM_IRQ(RTC_DCF77_TIMER));// catch interrupt in service routine
rtc_dcf77_time.day=1*((rtc_dcf77_frame>>36)&(0x1))+2*((rtc_dcf77_frame>>37)&(0x1))+4*((rtc_dcf77_frame>>38)&(0x1))+8*((rtc_dcf77_frame>>39)&(0x1))+10*((rtc_dcf77_frame>>40)&(0x1))+20*((rtc_dcf77_frame>>41)&(0x1));// read day of the month (01-31)
if(rtc_dcf77_time.day==0||rtc_dcf77_time.day>31){// day of the month should be 1-31
rtc_dcf77_time.weekday=1*((rtc_dcf77_frame>>42)&(0x1))+2*((rtc_dcf77_frame>>43)&(0x1))+4*((rtc_dcf77_frame>>44)&(0x1));// read day of the week (1=Monday - 7=Sunday)
if(rtc_dcf77_time.weekday==0||rtc_dcf77_time.weekday>7){// day of the week should be 1-7
rtc_dcf77_time.month=1*((rtc_dcf77_frame>>45)&(0x1))+2*((rtc_dcf77_frame>>46)&(0x1))+4*((rtc_dcf77_frame>>47)&(0x1))+8*((rtc_dcf77_frame>>48)&(0x1))+10*((rtc_dcf77_frame>>49)&(0x1));// read month of the year (01-12)
if(rtc_dcf77_time.month==0||rtc_dcf77_time.month>12){// month of the year should be 1-12
rtc_dcf77_time.year=1*((rtc_dcf77_frame>>50)&(0x1))+2*((rtc_dcf77_frame>>51)&(0x1))+4*((rtc_dcf77_frame>>52)&(0x1))+8*((rtc_dcf77_frame>>53)&(0x1))+10*((rtc_dcf77_frame>>54)&(0x1))+20*((rtc_dcf77_frame>>55)&(0x1))+40*((rtc_dcf77_frame>>56)&(0x1))+80*((rtc_dcf77_frame>>57)&(0x1));// read year of the century (00-99)
uint8_tintegral_i=0;// which bin has the highest integral/correlation
int16_tintegral_max=0;// maximum integral value found
for(uint8_tstart=0;start<(rtc_dcf77_phase_locked?10:LENGTH(rtc_dcf77_bins));start++){// which bin has been used to start the convolution (only use +/- 15 bits of previous phase if locked)
int16_tintegral=0;// value of the integral
for(uint8_tbin=0;bin<LENGTH(rtc_dcf77_bins);bin++){// go through bins to calculate correlation
int8_tdfc77_signal=-1;// the signal of the reference DCF77 signal
if(bin<10){// the signal is always high for the first 100 ms
dfc77_signal=1;// use highest values
}elseif(bin<20){// the signal has 50% chance of being high for the next 100 ms (encoding the bit)
dfc77_signal=0;// use middle value
}
// the rest of the time the signal is low (keep lowest value)
integral+=rtc_dcf77_bins[(start+bin+rtc_dcf77_phase+LENGTH(rtc_dcf77_bins)-5)%LENGTH(rtc_dcf77_bins)]*dfc77_signal;// calculate the correlation at this point and integrate it (start with previous phase - 15 bins)
}
if(integral>integral_max){// we found a better correlation result
integral_max=integral;// save new best result
integral_i=(start+rtc_dcf77_phase+LENGTH(rtc_dcf77_bins)-5)%LENGTH(rtc_dcf77_bins);// start new best phase start
}
}
if((int16_t)(integral_max+40)>rtc_dcf77_phase_max){// only save new phase if it is better than the last one, with some margin to compensate for the drift (perfect correlation = 100, worst correlation = -800)
rtc_dcf77_phase_max=integral_max;// save best phase value
rtc_dcf77_phase=integral_i;// save bin index corresponding to start of the phase