
The signal has an official range of 2000 km which covers most of Western Europe. 
More details in Wikipedia 
Some years ago I wrote a Turbobasic program to interpret and display the signal. It uses a receiver from Conrad electronics. Its signal goes through an ATmega8 in the hope of sharpening it up a bit - probably not essential - and is fed into a printer port (D sub 25) of a computer running MS-DOS 6.22 - obsolete but rock-solid. The signal format itself has not changed so you may like to convert the program ( listed below 'as is' ) to a modern platform. It can be used for the indoor sport of catching leap seconds.
I later wrote a pendulum-clock-checking program which compares the DCF77 signal to the swings of the pendulum and displays the variations on a graph.
' This gets the signal from the DCF77 transmitter and prints the time to screen
' It takes about 2 minutes for the program get synchronised with the signal
' There is no signal on the 59th second so there is a pause 
' in the display on the 58th second while waiting for the end of the 59th second.
' The program uses a Conrad receiver module via an ATmega8 chip and LPT2:
' The receiver should be sited away from a CRT monitor.
' The ferrite core of the receiver should be oriented flat-on to Frankfurt-am-Main.
' The signal consists of a 77.5 kHz signal which is reduced in amplitude to 15%
' to form spaces at 1 second intervals.
' The second starts on the leading (falling) flank of the space.
' The spaces are either 100 ms long which means: 0
'               OR      200 ms long which means: 1
' The series of 1's and 0's provides the time code.
' The 59th space in each minute is omitted to syncronise the receiver with
' the code.
' The program makes a note of the marks rather than the spaces since they are said
' to be less affected by thunderstorms.
' The code includes 3 parity bits (even parity) and 3 fixed bits. Actually, the
' second "fixed" bit, normally low, indicates a transmitter malfunction if high.
' The program "beeps" if the parity or fixed bits are incorrect.
' This version of the program uses a software loop to get the time values.
' Previous versions used the Turbo Basic TIMER function but its accuracy
' falls off after 54 ms.
' The marks are all circa 50 ms too short.
' Another approach would be to measure the events using the external
' microcontroller which would then relay the results via the serial port.
Start:
ON KEY(1) GOSUB Sayonara
KEY(1) ON
ON ERROR GOTO Start
CLS
?
? "Input -------  DCF time signal 77.5 kHz:    Space:      ms   Mark:      ms
COLOR  2,0
?
? "-------------------------------------------------------------------------------"
? "  10's ------             1         2         3         4         5         6"
? "Seconds -----    123456789012345678901234567890123456789012345678901234567890
? "                               this line is overwritten while synchronising"
COLOR 14,0
? "Signal ------
COLOR 2,0
? "Values ------                        1248124 124812 1248121241248112481248
? "  10's ------                            000     00     00       0    0000
COLOR 10,0
? "Interpretation  Weather code--- CET- Mins--- Hours- Days- Wk Mon  Year----
COLOR 14,0
? "Parity ------                  0    1       P      P                      P
COLOR 2,0
? "-------------------------------------------------------------------------------"
COLOR 7,0
?
? "DCF time ----
?
? "DCF date ----
?
? "PC time -----
'################# MAIN LOOP #####################
DO
'------------------------------------- Get signal - METHOD 1
   Count = 0                         ' Reset
   WHILE Signal = OldSignal          ' Wait while the signal is unchanged
     Signal = INP(&H278+1)           ' read parallel port LPT2:
     INCR Count                      ' count number of times Signal was read
   WEND
   OldSignal = Signal                ' update Signal
   Msec = INT(Count/277)             ' fudge Count into "milliseconds" Msec
                                     ' (divisor to suit your computer speed)
' ? Msec;
'------------------------------------- Get signal - METHOD 2
' MTIMER                             ' Start micro timer
' WHILE Signal = OldSignal           ' Wait while the signal is unchanged
'   Signal = INP(&H278+1)            ' read parallel port LPT2:
' WEND
' OldSignal = Signal                 ' update Signal
' Msec = INT(MTIMER/1000)            ' read and cook microseconds
'  ? Msec
   ' The lengths of the incoming marks and spaces are not recorded very
   ' accurately - there is interference on the leading flanks of the marks -
   ' so there is a range:
   '  50 -  150 Msecs counts as a short space (nominally 100 Msecs)
   ' 151 -  250 Msecs             long space  (nominally 200 Msecs)
   ' 500 -  850 Msecs             short mark, (nominally 800 Msecs)
   ' 851 - 1200 Msecs            long  mark, (nominally 900 Msecs)
   '     > 1200 Msecs              end of minute marker
   ' This program reads the marks only (it could be the spaces - or both)
  SELECT CASE Msec        ' Sort out what length of mark (or space)
                                            ' was received and act on it
      CASE 500 TO 850        ' 800 ms. mark following a 200 ms. space
          CALL GetSignal(Sec,Min,Hour,Day,WDay,Month,Year,CET$,Imm$,Pm,Ph,Pc)
                                            ' Interpret that signal
          CALL ShowSec(Sec,"1",Msec)    ' Display seconds and 1
      CASE 851 TO 1200      ' 900 ms. mark following a 100 ms. space
          CALL ShowSec(Sec,"0",Msec)    ' Display seconds and 0
      CASE > 1200                ' long "end of minute" marker
          CALL ShowSec(Sec,"0-0",Msec)                 ' Display seconds
          CALL ShowTime(Hour,Min,CET$,Imm$,Pm,Ph)    ' Display time and CET/CEST
          CALL ShowCalendar(Day,WDay,Month,Year,Pc)  ' Display calendar
          SOUND 1000, .5
          Sec = 0
     CASE 10 TO 499
          CALL ShowSpace(Msec)
  END SELECT
LOOP
'#################### SUB ROUTINES ##############
SUB ShowSpace(Msec)
  LOCATE 2,42 : ? "   "             ' blink signal
  LOCATE 2,51 : COLOR 15,0 : ? USING "#####"; Msec              ' print space
END SUB
'---------------------------
SUB ShowSec(Sec,Signal$,Msec)                                   ' display stuff
  IF Sec = 0 THEN LOCATE 7,75  : ? "   "                        ' wipe pointer
  INCR Sec
  LOCATE 2,  42 :     COLOR 14,0   : ? Signal$
  LOCATE 2,  67 :     COLOR 15,0   : ? USING "#####"; Msec      ' mark
  LOCATE 7,  Sec+16                              : ? " |"       ' pointer
  LOCATE 8,  Sec+16:  COLOR 14,0   : ? Signal$  : COLOR 15,0
  LOCATE 15, 22:      COLOR 15,0   : ? RIGHT$(STR$(100 + Sec),2)
  LOCATE 19, 16:      COLOR  7,0   : ? TIME$
  LOCATE  8, 17:      COLOR 15,0   : ? " "                      ' wipe signal
  IF Sec = 59 THEN
     LOCATE 7,Sec + 17 :             ? " |"                     ' minute marker
  END IF
END SUB
'----------------------------
SUB ShowTime(Hour,Min,CET$,Imm$,Ph,Pm)         ' display hours, mins, CETs
  LOCATE 15, 16:      COLOR 15,0  : ? USING "##:##:"; Hour, Min;
IF Imm$ <> "" THEN
  LOCATE 20, 26:  COLOR 15,0  : ? Imm$ : EXIT SUB
ELSE
  LOCATE 20, 26: ? SPACE$(30)
END IF
  LOCATE 15, 26:      COLOR 15,0  : ? CET$
  IF Ph/2 <> INT(Ph/2) THEN BEEP                         ' beep if parity error
  IF Pm/2 <> INT(Pm/2) THEN BEEP                         ' ditto
END SUB
'----------------------------
SUB ShowCalendar(Day,WDay,Month,Year,Pc)                 ' display calendar
SELECT CASE WDay
  CASE 1:  WDay$  = "Monday,"
  CASE 2:  WDay$  = "Tuesday,"
  CASE 3:  WDay$  = "Wednesday,"
  CASE 4:  WDay$  = "Thursday,"
  CASE 5:  WDay$  = "Friday,"
  CASE 6:  WDay$  = "Saturday,"
  CASE 7:  WDay$  = "Sunday,"
END SELECT
SELECT CASE Month
  CASE 1:  Month$ = "January"
  CASE 2:  Month$ = "February"
  CASE 3:  Month$ = "March"
  CASE 4:  Month$ = "April"
  CASE 5:  Month$ = "May"
  CASE 6:  Month$ = "June"
  CASE 7:  Month$ = "July"
  CASE 8:  Month$ = "August"
  CASE 9:  Month$ = "September"
  CASE 10: Month$ = "October"
  CASE 11: Month$ = "November"
  CASE 12: Month$ = "December"
END SELECT
LOCATE 17, 16  : COLOR 15,0
  ? WDay$; Day; Month$;
  ? USING " 20##        "; Year
  COLOR 7,0
  IF Pc/2 <> INT(Pc/2) THEN BEEP        ' beep if parity error
END SUB
'-----------------------------
'Interpret the signal bits according to the second on which they arrived
SUB GetSignal(Sec,Min,Hour,Day,WDay,Month,Year,CET$,Imm$,Pm,Ph,Pc)
  Imm$ = ""
  SELECT CASE Sec
    CASE 0  '   : BEEP                   ' this bit is always reset !
    CASE 1 TO 14:
               Min = 0 : Hour = 0 : Day = 0 : WDay = 0 : Month = 0 : Year = 0
               Pm = 0 : Ph = 0 : Pc = 0
      '1 to 14 is a coded commercial weather forecast. The code has been broken
      'by Microcontroller.net but not published. It took them 3 years.
      'I believe the time provided a key to the code
    CASE 15 : CET$  = "Abnormal transmitter operation"
    CASE 16 : Imm$  = "A time change is imminent     "
    CASE 17 : CET$  = "Central European Summer Time  "
    CASE 18 : CET$  = "Central European Time         "
    CASE 19 : Imm$  = "A leap second is imminent     "
      '  20                                 this bit is always set
    CASE 21 : Min   = Min + 1    : INCR Pm
    CASE 22 : Min   = Min + 2    : INCR Pm
    CASE 23 : Min   = Min + 4    : INCR Pm
    CASE 24 : Min   = Min + 8    : INCR Pm
    CASE 25 : Min   = Min + 10   : INCR Pm
    CASE 26 : Min   = Min + 20   : INCR Pm
    CASE 27 : Min   = Min + 40   : INCR Pm
    CASE 28 :                    : INCR Pm  'parity bit minutes
    CASE 29 : Hour  = Hour + 1   : INCR Ph
    CASE 30 : Hour  = Hour + 2   : INCR Ph
    CASE 31 : Hour  = Hour + 4   : INCR Ph
    CASE 32 : Hour  = Hour + 8   : INCR Ph
    CASE 33 : Hour  = Hour + 10  : INCR Ph
    CASE 34 : Hour  = Hour + 20  : INCR Ph
    CASE 35 :                    : INCR Ph  'parity bit hours
    CASE 36 : Day   = Day + 1    : INCR Pc
    CASE 37 : Day   = Day + 2    : INCR Pc
    CASE 38 : Day   = Day + 4    : INCR Pc
    CASE 39 : Day   = Day + 8    : INCR Pc
    CASE 40 : Day   = Day + 10   : INCR Pc
    CASE 41 : Day   = Day + 20   : INCR Pc
    CASE 42 : WDay  = WDay + 1   : INCR Pc
    CASE 43 : WDay  = WDay + 2   : INCR Pc
    CASE 44 : WDay  = WDay + 4   : INCR Pc
    CASE 45 : Month = Month + 1  : INCR Pc
    CASE 46 : Month = Month + 2  : INCR Pc
    CASE 47 : Month = Month + 4  : INCR Pc
    CASE 48 : Month = Month + 8  : INCR Pc
    CASE 49 : Month = Month + 10 : INCR Pc
    CASE 50 : Year  = Year  + 1  : INCR Pc
    CASE 51 : Year  = Year  + 2  : INCR Pc
    CASE 52 : Year  = Year  + 4  : INCR Pc
    CASE 53 : Year  = Year  + 8  : INCR Pc
    CASE 54 : Year  = Year  + 10 : INCR Pc
    CASE 55 : Year  = Year  + 20 : INCR Pc
    CASE 56 : Year  = Year  + 40 : INCR Pc
    CASE 57 : Year  = Year  + 80 : INCR Pc
    CASE 58 :                    : INCR Pc          'parity bit calendar
 END SELECT
END SUB
Sayonara:
END