DCF77 Clock

The Conrad DCF Receiver artnr. 641138
bit (seconde) naam doel
0 M Minuutmarkering
1-14 gereserveerd
15 R 1 als reserve-zendantenne in gebruik is
16 A1 aankondiging omschakeling zomer/wintertijd
17-18 Z1, Z2 01 tijdens wintertijd, 10 tijdens zomertijd
19 A2 aankondiging van schrikkelseconde
20 S Start van tijdsbericht, altijd 1
21-24 eenheden minuten
25-27 tientallen minuten
28 P1 controlesom van bit 21-27
29-32 eenheden uren
33-34 tientallen uren
35 P2 controlesom bit 29-34
36-39 eenheden datum
40-41 tientallen datum
42-44 dag van de week
45-48 eenheden maand
49 tiental maand
50-53 eenheden jaartal (0..9)
54-57 tientallen jaartal (0..9)
58 P3 controlesom bit 36-57
(59) ontbrekende impuls; markeert einde van een minuut
-- DCF 77 Clock
-- Version xx.xx
--include 16f877a_bert
include 16f628a_bert
include lcd_44780_16f628
-- 20 MHz crystal with 2 20pF capacitors
-- 33k on MCLR to +5V
-- Conrad DCF Receiver artnr. 641138
-- Pin 1: Ground
-- Pin 2: +5v and Pull-up resistor 10k to pin 3
-- Pin 3: DCF port to PIC input port and Pull-up resistor 10k to pin 2
-- Pin 4: Not connected


-- Define variables
var byte low_cnt,sec_cnt,counter,positie, tmp
var byte sec[59]
var byte min
var byte hour
var byte utc
var byte day
var byte day_week[2]
var byte month
var byte year
var byte zt1
var byte zt2
--pin B1 voor DCF77 input
var bit dcf is pin_b1
-- -------------------
var byte day_week_ma[2]={"M","a"}
var byte day_week_di[2]={"D","i"}
var byte day_week_wo[2]={"W","o"}
var byte day_week_do[2]={"D","o"}
var byte day_week_vr[2]={"V","r"}
var byte day_week_za[2]={"Z","a"}
var byte day_week_zo[2]={"Z","o"}

--
pin_b1_direction = input

--Set global variables

low_cnt=0
lcd_cursor=off
sec_cnt=0
min=0
hour=0
utc=0
day=0
month=0
year=0
zt1=0
zt2=0


--======================================================================
function even_parity(byte in start_bit,byte in end_bit) return bit is
-- Funtie om te bepalen of een reeks bits even parity heeft. Wanneer even dan
-- is even_parity true.
-- DCF77 werkt met even pariteit, 1 voor minuten, uren en de datum
-- bit 28 P1 = even pariteit voor de minuten
-- bit 35 P2 = even pariteit voor de uren
-- bit 58 P3 = even pariteit voor de datum
var bit even
var byte par
par = 0
while start_bit <= end_bit loop if (sec[start_bit]>0) then
            par = par+1
        end if
start_bit = start_bit + 1
end loop
if par%2 > 0 then
   even = 0
else
   even = 1
end if
return even
end function
--=======================================================================
procedure set_var is
--Zomertijd zt1 = 0=winter 1= zomer
--Zomertijd zt2 = 1=winter 0= zomer
zt1=sec[17]
zt2=sec[18]
min=(sec[25]+sec[26]*2+sec[27]*4)*10+(sec[21]+sec[22]*2+sec[23]*4+sec[24]*8)
hour=(sec[33]+sec[34]*2)*10+(sec[29]+sec[30]*2+sec[31]*4+sec[32]*8)
day=(sec[40]+sec[41]*2)*10+(sec[36]+sec[37]*2+sec[38]*4+sec[39]*8)
month=sec[49]*10+(sec[45]+sec[46]*2+sec[47]*4+sec[48]*8)
year=(sec[54]+sec[55]*2+sec[56]*4+sec[57]*8)*10+ sec[50]+sec[51]*2+sec[52]*4+sec[53]*8
tmp=sec[42]+sec[43]*2+sec[44]*4
case tmp of
        1 : day_week=day_week_ma
        2 : day_week=day_week_di
        3 : day_week=day_week_wo
        4 : day_week=day_week_do
        5 : day_week=day_week_vr
        6 : day_week=day_week_za
        7 : day_week=day_week_zo
        otherwise day_week=day_week_za
end case

--utc=hour-1-zt1
utc=hour-1-zt1

if utc > 54 then
 utc=23
end if
if utc > 53 then
 utc=22
end if


end procedure
--=======================================================================
procedure display is
--Tijd en datum schrijven op LCD
    LCD_clock_line_pos(hour,0,0)
    LCD_char_line_pos(":",0,2)
    LCD_clock_line_pos(min,0,3)
    LCD_char_line_pos("U",0,6)
    LCD_char_line_pos("T",0,7)
    LCD_char_line_pos("C",0,8)
    LCD_char_line_pos(":",0,9)
    LCD_clock_line_pos(utc,0,11)
    LCD_char_line_pos(":",0,13)
    LCD_clock_line_pos(min,0,14)
    counter=0
    positie=2
    for 2 loop
        LCD_char_line_pos(day_week[counter],1,positie)
        counter=counter+1
        positie=positie+1
    end loop
    LCD_clock_line_pos(day,1,5)
    LCD_char_line_pos("-",1,7)
    LCD_clock_line_pos(month,1,8)
    LCD_char_line_pos("-",1,10)
    LCD_clock_line_pos(year,1,11)
end procedure
--=======================================================================
--start  main loop
LCD_char_line_pos("W",0,0)
LCD_char_line_pos("a",0,1)
LCD_char_line_pos("i",0,2)
LCD_char_line_pos("t",0,3)

LCD_char_line_pos("P",1,6)
LCD_char_line_pos("A",1,7)
LCD_char_line_pos("1",1,8)
LCD_char_line_pos("K",1,9)
LCD_char_line_pos("W",1,10)
forever loop
--Controleren of dcf hoog is
if dcf then
   low_cnt=0
    delay_1ms(150)
    if dcf then
       sec[sec_cnt]=1
       LCD_char_line_pos("-",1,15)
    else
       sec[sec_cnt]=0
       LCD_char_line_pos("_",1,15)
    end if
    sec_cnt=sec_cnt+1
--Wachten todat hoog signaal laag is
    while dcf loop
    end loop
--beveiliging, niet meer dan 60 maal sec_cnt
    if sec_cnt>59 then
     sec_cnt=0
    end if
else
--tellen van laag, meer dan 1 sec dan start puls
   low_cnt=low_cnt+1
   if low_cnt>52 then
    low_cnt=0
    sec_cnt=0
     LCD_char_line_pos(" ",1,15)
   else
    delay_1ms(20)
   end if
end if
-- display datum en tijd
-- bit 20 = Startbit, is altijd 1
-- bit 28 P1 = even pariteit voor de minuten
-- bit 35 P2 = even pariteit voor de uren
-- bit 58 P3 = even pariteit voor de datum

if sec[20] & even_parity(29,35) & even_parity(29,35) & even_parity(36,58) then
   set_var
   display
end if
end loop