0 | begin of minute (always 0?) |
1-14 | reserved |
15 | reserve antenna activated |
16 | announcement: dts(summer time)/no dts change |
17 | day time saving (summer time) active |
18 | day time daving (summer time) not active |
19 | announcement: leap second |
20 | begin of time information (always 1) |
21-27 | minute |
28 | parity minute |
29-34 | hour |
35 | parity hour |
36-41 | day |
42-44 | weekday |
45-49 | month |
50-57 | year |
58 | parity date |
Switching from day time saving to non-dst is announced by setting bit
16 for one hour. Also for an hour bit 19 is set to announce a leap second.
The minute in which the leap second is inserted is 61 seconds long - then
bit 59 is transmitted as logical 0 and bit 60 is skipped to mark the beginning
of the next minute.
The time and date information is BCD encoded which means the bit values
are
1, 2, 4, 8, 10, 20, 40, 80and not as usual
1, 2, 4, 8, 16, 32, 64, 128.The parity bit states if the sum of bits (each with value 1) is even (0) or odd (1).
main.c | Initializes all functions and provides callback functions. |
timer.c, timer.h | Initialisation and reading timer 1 for period measurement. |
uart.c, uart.h | Sending blocks of data to UART. |
dcf77.c, dcf77.h | Decoding the time signal. |
led.h | Definitions for LED toggling |
global.h | globale definitions (e.g. typedefs) |
The most important module is DCF77.C of course. I contains the interrupt
handler for external INT1 as well as the decoding of the time signal. Without
going to deep into details of implementation, just this: because alternated
triggering for falling and rising edges is needed, the control register
is configured inside the INT1 handler accordingly. The falling edge marks
the start of a new second, the passed time until the rising edge is measured
and used to dertemine whether a logical 0 (<0.15s) or a logical 1 (<0.25s)
was trasmitted. Just so the time between the rising and the next falling
edge is measured: if it's >1.5s, the skipped 59th second was detected and
the next falling edge marks second 0.
On the rising as well as on the falling edge, callback routines can
be called (dcf77_call_fall, dcf77_call_rise). How this works can be examined
in the main program. The callback functions are used to send the decoded
time info to the UART and to toggle status LEDs. The LEDs are used as follows:
LED 0 | Shows input signal. 'off' means low input level, 'on' mean high level. |
LED 1 | Shows if the skipped 59th second was detected and thus the current second is known ('on' = yes). |
LED 2 | Shows state of last received bit ('on' = 1, 'off' = 0). |
The decoded time info is stored in a buffer of 9 bytes length. The bytes
have the following meanings:
0 | dcf77_start | starting byte: always 0xfe |
1 | dcf77_second | current second (0-59) |
2 | dcf77_minute | minute (0-59) |
3 | dcf77_hour | hour (0-11) |
4 | dcf77_day | day (1-31) |
5 | dcf77_wday | weekday (1-7, 1: Montag, ... , 7: Sonntag) |
6 | dcf77_month | month (1-12) |
7 | dcf77_year | year (0-99) |
8 | dcf77_status | status bits |
Be aware that the values for minute, hour etc. are not valid before
the beginning of the next minute. Furthermore, the second variable never
reaches 59, since this second is not sent. The 9th byte contains status
bit which are defined as follows:
0 | DCF77_STATUS_BIT | last bit received |
1 | DCF77_STATUS_INIT | skipped 59th bit detected (1 = yes) |
2 | DCF77_STATUS_MIN_VALID | minute information valid (1 = yes) |
3 | DCF77_STATUS_HOUR_VALID | hour information valid (1 = yes) |
4 | DCF77_STATUS_DATE_VALID | date information valid (1 = yes) |
The 1st bit (BIT) makes it possible to decode the whole time info outside
the module using the current second (dcf77_second). Though this doesn't
make much sense, this makes information visible to the outside which are
ignored by DCF77 (like announcement of leap second and dst switching).
The bit INIT indicates if the skipped 59th second was detected, which
means the seconds are synchronized. If this bit is zero, the value in dcf77_second
is not the current second, but just a synchronizing counter which is incremented
every second. Accordingly, all other time info is also invalid if this
bit is zero.
The bits MIN_VALID, HOUR_VALID and DATE_VALID indicate if the parity
bit of the corresponding time information was correct and that the begin
of time information was marked tht right way (bit 20 == 1 ?).
dcf77 <comport> [format]The format parameter values have the following meanings:
e.g.: dcf77 com2: 2
0 | output bitwise ('*' = 1, '-' = 0). |
1 | output the 9 received bytes as raw hex numbers. |
2 | formatted output of date and time [default] |
The formatted output shows the currently decoded information. So the
minute is increased at the 28th second, while a real clock changes the
minute only if the second reaches 0 (this also true for the remaining info
of course).
To compile the sources you need either MS Visual C++ (5.0) or CygWin32
(20.1). Project files as well as a makefile for Visual C are included (dcf77.mak);
the makefile for Cygwin is named 'Makefile'. By changing the LANGUAGE definition
you can create either a German (LANGUAGE=0) or English (LANGUAGE=1) version.