Here the sourcefile from a guy from the Netherlands who did a project with a Conrad DCF-77 receiver and Picbasic. Look at his fabulous site
I personally prefer to use C but for the first steps i did use this for the trial-and-error period and it worked right away.
;V-2
;Compile with Crownhill Proton+ PIC Basic compiler.
;Receives DCF77 data from a standard DCF module and shows date/time on a LCD.
;It is important that the DCF77 reception is optimal.
;For DCF77 info, schematic diagram and control: www.picbasic.nl
; PIC16F628A: +--v--+
; Pulse for gong E1 <[ ]> One pulse per second
; Pulse for gong E2 <[ ]> Daylight saving, high when it's summer
; Volume level gong <[ ]< Connect LDR to +5V, 1M potmeter to GND
; [ ]< 12:00 (AM/PM) or 24:00 notation
; GND [ ] +5V
; DCF77 module signal >[ ]> DB7 LCD
; Normaly open, for test to GND >[ ]> DB6 LCD
; LCD EN <[ ]> DB5 LCD
; LCD RS <[ ]> DB4 LCD
; +-----+
;Er is ook een Nederlandse versie / There is a Dutch version too
;www.picbasic.nl / Frits Kieftenbelt, Raalte, Netherlands (Frizie)
DEVICE = 16F628A
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF ;On-chip RC-oscillator
ALL_DIGITAL TRUE
;Normal aliases (constants)
SYMBOL CharType = 255 ;Maximal 255: 255 is the ASCII code for a block in the LCD time bar
SYMBOL LCD_Char = 16 ;Minimal 16: Number of characters of each line (dependence on LCD device)
SYMBOL MaxFindTime = 65 ;Minimal 65: (Sec) Time to find the startsequence (second 00)
SYMBOL PulseLength = 740 ;Minimal 500! Maximal 750: (mSec)
SYMBOL PulseLengthX= PulseLength / 10
SYMBOL StartUpTime = 45000 ;Maximal 65535: (mSec) 45 seconds startup time for the DCF77 receiver after power-on
;Logical aliases (constants)
SYMBOL AAN = 0 ;Reversed ON
SYMBOL FALSE = 0
SYMBOL OFF = 0
SYMBOL ON = 1
SYMBOL TRUE = 1
SYMBOL UIT = 1 ;Reversed OFF
;Port aliases
SYMBOL DaylightSav = PORTA.0 ;High when it's summer
SYMBOL SecondPulse = PORTA.1 ;Pulses every second a half second
SYMBOL Gong1 = PORTA.2 ;Pulses high every whole hour, to steer the gong
SYMBOL Gong2 = PORTA.3 ;Pulses high every whole and half hour, to steer the gong
SYMBOL Volume = PORTA.4 ;Changing between output (GND) and input (3-state) for regulate the volume level from the gong
SYMBOL AM_PM = PORTA.6 ;Connect for 24 hours mode to +5V, for 12 hours AM/PM notation to GND
SYMBOL LDR = PORTA.7 ;When it's dark (LDR sensor), sounds the gong softly
SYMBOL DCF_Signal = PORTB.0 ;Input for the DCF77 module (receiver) signal (i.e. Conrad BN641138)
SYMBOL Test = PORTB.1 ;Input leave normaly open, for adjusting LDR, make low BEFORE startup the PIC, for adjusting gong, make low AFTER startup the PIC
; 76543210
TRISA = %11100000
TRISB = %11111111
PORTB_PULLUPS ON ;Pull-up for DCF77 receiver and Test button
;WORD
DIM SignalCheck AS WORD
DIM Teller AS WORD ;Teller = Counter
;BYTE
DIM BitNumber AS BYTE
DIM CursorPos AS BYTE ;Cursor x-position on LCD
DIM Day AS BYTE
DIM GeneralCounter AS BYTE
DIM Hour AS BYTE
DIM HourDCF AS BYTE
DIM HourLCD AS BYTE
DIM Minute AS BYTE
DIM MinuteDCF AS BYTE
DIM Month AS BYTE
DIM ReceiveByte AS BYTE
DIM Second AS BYTE
DIM WeekDay AS BYTE
DIM Year AS BYTE
DIM BD1 AS BYTE ;Byte Dummy 1
;BIT
DIM Initialize AS BIT ;TRUE when initializing
DIM ParityBit AS BIT
DIM ParityError AS BIT
DIM ReceiveBit AS BIT
DIM Signal AS BIT ;TRUE when signal is found
DIM ID1 AS BIT ;Bit Dummy 1
PORTA = 0
PORTB = 0
CLEAR
DELAYMS 200 ;LCD stabilize
CLS
PRINT "www.picbasic.nl"
DELAYMS 3000
CLS
PRINT "DCF16UKD V-2" ;Version number
DELAYMS 2000
CLS
PRINT "Adjust LDR"
WHILE Test = AAN ;If Test = LOW when startup the PIC, the LDR can adjust with the indication from the Daylightsave LED
IF LDR = ON THEN
DaylightSav = TRUE
ELSE
DaylightSav = FALSE
ENDIF
WEND
CLS
PRINT "Search signal"
Initialize = TRUE
LOW Volume ;When startup the PIC, the gong volume is loud
GOTO MainLoop ;Jump over the subroutines
;SUBROUTINES
ReceiveBitNumber: ;Fill the receivebyte with the requested amount of bits in BCD mode
CLEAR ReceiveByte
FOR BD1 = 0 TO BitNumber - 1
GOSUB ReceiveOneBit
IF ReceiveBit = 1 THEN SETBIT ReceiveByte, BD1
NEXT
ReceiveByte = ((ReceiveByte >> 4) * 10) + (ReceiveByte & 15) ;BCD (Binary-Coded Decimal) to byte conversion
RETURN
ReceiveOneBit: ;Receive a bit and store it in ReceiveBit
CLEAR Teller
WHILE DCF_Signal = AAN
DELAYMS 1
INC Teller
IF Teller > 3000 THEN ReceiveError
WEND
DELAYMS 155 ;135 - 175msec
ReceiveBit = DCF_Signal
IF Initialize = TRUE THEN
CursorPos = (Second * LCD_Char) / 58 ;Calculate where the cursor position must be (dependence on waittime and LCD device)
PRINT AT 2, CursorPos, CharType ;Make time bar actual
ELSE
PRINT AT 1, CursorPos, DEC2 Second ;Print the seconds on LCD
ParityBit = ParityBit + ReceiveBit ;Bit, thus 0+0=0 / 0+1=1 / 1+1=0 / 1+0=1 On the end you can see if it is even or uneven
ENDIF
INC Second ;Because we are in this routine every second, we can use it to count seconds
SecondPulse = ON ;Outputsignal second pulse
DELAYMS 500
SecondPulse = OFF
DELAYMS PulseLength - 500
RETURN
;MAINPROGRAM
MainLoop:
CLEAR GeneralCounter
Second = 00 ;Start with first second
Signal = FALSE
WHILE Signal = FALSE ;Wait while DCF_Signal is high
CLEAR Teller
WHILE DCF_Signal = UIT
INC Teller
DELAYMS 1
IF Teller > StartUpTime THEN ReceiveError ;Startup time for the DCF77 receiver by power-on
WEND
CLEAR Teller
WHILE DCF_Signal = AAN ;Start counting time between pulses
INC Teller
DELAYMS 10
IF Initialize = FALSE THEN
SELECT CASE Teller
CASE 85 - PulseLengthX ;85 = (1000mSec - 155mSec) / 10
PRINT AT 1, CursorPos, "59";xx:xx:59, Print the missing second on LCD
CASE 25
SecondPulse = ON
CASE 75
SecondPulse = OFF
CASE 250
GOTO ReceiveError ;Signal doesn't change within time
ENDSELECT
ELSE
IF Teller > (StartUpTime / 10) THEN ReceiveError ;Startup time for the DCF77 receiver by power-on
ENDIF
WEND
IF GeneralCounter >= MaxFindTime THEN ReceiveError ;If more then 'MaxFindTime' seconds counted then we have a problem
INC GeneralCounter
IF Teller > 100 THEN Signal = TRUE ;We count per 10mSec, so we need at least 100x10mSec for finding the startsequence
IF Initialize = TRUE THEN
CursorPos = (GeneralCounter * LCD_Char) / MaxFindTime ;Calculate where the cursor position must be (dependence from first waittime and LCD type)
PRINT AT 1, 1, "Found signal "
PRINT AT 2, CursorPos , CharType ;Put block characters on LCD while waiting for initialize signal
ENDIF
WEND
IF Initialize = TRUE THEN
CLS
PRINT "Initialize..."
PRINT AT 2, 1, REP "_" \ LCD_Char ;Draw the waiting time bar length
ELSE
CursorPos = LCD_Char - 9 ;X-position from time on LCD
CURSOR 1, CursorPos
IF ParityError = TRUE THEN ;Tijd not 100%, the PIC self calculates the time now for actualising
IF Minute < 59 THEN
INC Minute
ELSE
Minute = 00 ;\
IF Hour < 23 THEN ;-Time is synchronized, in spite of parityerror
INC Hour ;/
ELSE
Hour = 00 ;Actualising the date have no sense, when an error occured then it isn't gonna changed
ENDIF
ENDIF
ELSE ;No error, put the normal DCF time on LCD
Minute = MinuteDCF
Hour = HourDCF
ENDIF
IF AM_PM = AAN THEN ;If AM/PM notation is selected then...
SELECT CASE Hour
CASE 0 :HourLCD = 12 ;If it's 00:xx then put on LCD: 12:xx
CASE > 12:HourLCD = Hour - 12 ;If it's between 13:xx and 23:xx then put on LCD: 1:xx / 11:xx
END SELECT
ELSE ;...else, it's 24 hour notation...
HourLCD = Hour ;The hour which comes on LCD is equal to the DCF hour
PRINT " " ;Erase AM/PM when switching from 12 hours notation to 24 hours notation
ENDIF
IF HourLCD < 10 THEN PRINT " " ;Clear leading zero (08:00:00 --> 8:00:00) (Null suppression)
PRINT DEC HourLCD, ":", DEC2 Minute, ":00" ;Put actual time on LCD every minute
IF AM_PM = AAN THEN ;If AM/PM notation is selected then...
IF Hour < 12 THEN ;...if it's AM then...
PRINT "am" ;...put AM on LCD next to the time...
ELSE ;...anders (afternoon)...
PRINT "pm" ;...put PM on LCD next to the time
ENDIF
CursorPos = LCD_Char - 3 ;Put cursor position already for the seconds, 2 more to the left for AM/PM
ELSE
CursorPos = LCD_Char - 1 ;Put cursor position already for the seconds
ENDIF
IF Minute = 00 OR Minute = 30 OR Test = AAN THEN GongSignal ;Every whole and half hour a gong signal (and every minute if Test is enabled)
ENDIF
IF Signal = TRUE THEN ;Startbit succesfull received, start filling data
GOSUB ReceiveOneBit ;0: Bit 0 (reserved (DCF77 protocol))
Further: ;When the gong sounds, bit 0 is ignored, after a gong, it goes further here
FOR BD1 = 1 TO 14 ;1...14: first 15 bits are reserved (info see www.picbasic.nl --> DCF77 info)
GOSUB ReceiveOneBit
NEXT
CLEAR ParityBit ;If ParityError is set, then ParityBit is also mutated, thus reset
CLEAR ParityError ;Reset PariteitsError (Leave these 2 resets on this place, because when a parityerror happens during initializing)
GOSUB ReceiveOneBit ;15: Which send antenna is used?
; IF ReceiveBit = 0 THEN... ;Signal is sended by the standard antenna, this bit is not used in this program
; IF ReceiveBit = 1 THEN... ;Signal is sended by a reserve antenna, this bit is not used in this program
GOSUB ReceiveOneBit ;16: Switch summer/winter next hour?
; IF ReceiveBit = 1 THEN... ;This bit is not used in this program
GOSUB ReceiveOneBit ;17: Daylight Savings Time?
IF ReceiveBit = 1 THEN
DaylightSav = ON ;Summer
ELSE
DaylightSav = OFF ;Winter
ENDIF
FOR BD1 = 18 TO 19 ;18...19: Skip bits (Time Zone bit 2 and leap-second bit)
GOSUB ReceiveOneBit
NEXT
GOSUB ReceiveOneBit ;20: Startbit, must always be a 1, not used in this program
; IF ReceiveBit = 0 THEN... ;This bit is not used in this program
BitNumber = 7 ;21...27: Receive Minute (7 bits)
GOSUB ReceiveBitNumber
MinuteDCF = ReceiveByte
GOSUB ReceiveOneBit ;28: Parity bit 1, minutes
IF ParityBit = ON THEN ParityError = TRUE
BitNumber = 6 ;29...34: Receive Hour (6 bits)
GOSUB ReceiveBitNumber
HourDCF = ReceiveByte
GOSUB ReceiveOneBit ;35: Parity bit 2, hours
IF ParityBit = ON THEN ParityError = TRUE
BitNumber = 6 ;36...41: Receive Day (6 bits)
GOSUB ReceiveBitNumber
Day = ReceiveByte
BitNumber = 3 ;42...44: Receive WeekDay (3 bits)
GOSUB ReceiveBitNumber
WeekDay = ReceiveByte
BitNumber = 5 ;45...49: Receive Month (5 bits)
GOSUB ReceiveBitNumber
Month = ReceiveByte
BitNumber = 8 ;50...57: Receive Year (8 bits)
GOSUB ReceiveBitNumber
Year = ReceiveByte
GOSUB ReceiveOneBit ;58: Parity bit 3, date
IF ParityBit = ON THEN ParityError = TRUE
IF Initialize = TRUE THEN
IF ParityError = FALSE THEN ;If there is NO parityerror, then we are...
Initialize = FALSE ;...ready with initializing (If there IS a parityerror while initializing, then initialize again)
ENDIF
CLS
ENDIF
IF ParityError = FALSE THEN;Only actualise the date when there is no parity error
' PRINT AT 1, 1, REP " " \ 9 ;Erase the day on LCD (Only necessary with full name of the day)
PRINT AT 2, 1, REP " " \ LCD_Char ;Erase the whole 2nd line
CURSOR 1, 1
SELECT CASE WeekDay
CASE 1: PRINT "Mon"
CASE 2: PRINT "Tue"
CASE 3: PRINT "Wed"
CASE 4: PRINT "Thu"
CASE 5: PRINT "Fry"
CASE 6: PRINT "Sat"
CASE 7: PRINT "Sun"
ENDSELECT
PRINT AT 2, 1, DEC Day, " "
SELECT CASE Month
CASE 1: PRINT "January"
CASE 2: PRINT "February"
CASE 3: PRINT "March"
CASE 4: PRINT "April"
CASE 5: PRINT "May"
CASE 6: PRINT "June"
CASE 7: PRINT "July"
CASE 8: PRINT "August"
CASE 9: PRINT "September"
CASE 10: PRINT "October"
CASE 11: PRINT "November"
CASE 12: PRINT "December"
END SELECT
IF Month = 9 THEN
PRINT " '", DEC2 Year ;Else September (9 characters) doesn't fit on a 16 characters LCD
ELSE
PRINT " 20", DEC2 Year
ENDIF
ENDIF
ELSE ;Else 'Signal' = FALSE, we have no signal found
GOTO ReceiveError
ENDIF
GOTO MainLoop
GongSignal:
IF LDR = ON THEN ;If there is daylight or the shadedlamps are switched on, then...
LOW Volume ;...Volumepin low = Volume from gong louder...
ELSE ;...else (is it dark in the living-room)...
INPUT Volume ;...Volumepin 3-state = Volume from gong softly
ENDIF
DELAYMS 155
IF Minute = 00 OR Test = AAN THEN Gong1 = ON ;On the whole hours (and with Test) follows a 3-tone signal
Gong2 = ON ;On the half hours only a 2-tone signal
SecondPulse = ON ;Ondertussen gaat ook de seconde puls gewoon door
DELAYMS 500
Gong1 = OFF
Gong2 = OFF
SecondPulse = OFF
DELAYMS 330 ;985 - 500 - 155
INC Second
; When using the method underneath (with time instead of LDR), then erase the LDR syntax part above
; IF Hour > 5 THEN ;Between 0:30 and 6:30 is the gong volume not loud
; LOW Volume ;Volumepin low = Volume louder
; ELSE
; INPUT Volume ;Volumepin 3-state = Volume softly
; ENDIF
GOTO Further ;Go further with receiving the DCF bits from bit 15 (we omit bits 0...14)
ReceiveError:
CLS
PRINT "No signal" ;Startbit not found or no signal?
REPEAT
CLEAR ;Erase all RAM
ID1 = DCF_Signal
WHILE DCF_Signal = ID1 ;Wait for signal changing
INC SignalCheck
DELAYMS 1
WEND
ID1 = ID1 ^ 1
WHILE DCF_Signal = ID1 ;Wait for signal changing
INC SignalCheck
DELAYMS 1
WEND
UNTIL SignalCheck < 990
Initialize = TRUE ;Initialize again after the error
GOTO MainLoop
;V-2 to V-1:
;With parity check
;PulseLength as long as possible
;SecondPulse is now precise 0,5 sec