PC-Funkuhr am Printerport
=========================


Beschreibung
------------
Die von Conrad vertriebene, recht günstige DCF77 Uhr am Printerport hat einen
Nachteil: Sie kommt ohne SW für Linux daher. Diesen Nachteil habe ich versucht
zu ändern. Das Ergebnis ist pcf77!

Leider kann unter einem nicht-echtzeitfähigen OS wie Linux kein user-Programm
die genauen Timingwerte einhalten, wie sie die PC-Funkuhr zur Kommunikation
erwartet. Eine Auflösung von ca. 1 Millisekunde habe ich jedenfalls nicht
realisieren können.

Deshalb muss die Aufgabe zweigeteilt werden: Zunächst muss ein Kernel-Prozess
die Funkuhr auslesen. Die gefundenen Werte werden anschließend von einem
normalen User-Prozess in verwertbare Zeitinformationen umgewandelt. Ich habe
auf meiner Kiste die Printer-Driver als Module konfiguriert, sodass man sehr
schnell und ohne Neustart die notwendigen Kernel-Patches einbringen und
austesten kann. (Man beachte dabei, dass das ioctl-Kommando LPPCFTIMER nur
inoffiziell ist. Ich hoffe, dass es keine Überschneidungen mit anderen
ioctl-Kommandos gibt und geben wird!)

Die Zweiteilung der Aufgabe bedeutet auf der anderen Seite, dass (im Prinzip)
auch andere Hardwareplattformen als Intel-PCs in den Genuss der PC-Funkuhr
kommen können. Leider steht mir kein solcher Rechner zur Verfügung, sodass ich
keine diesbezüglichen Tests und Anpassungen unternehmen konnte.

Auch wenn hier der Kernel >2.4.x unterstützt wird, habe ich kein separates
PARPORT-Treiber Modul geschrieben, da die Funkuhr in einem Centronics-Kabel
eingebaut ist und somit nur ein Drucker angeschlossen werden kann. Ich
interpretiere dies dahingehend, dass die Uhr gleichsam im Drucker enthalten
ist, somit also auch der lp-Treiber zuständig ist. 

Das Programm pcf77 kommuniziert nun mit dem gepatchten Treiber und wandelt die
Zeitinformationen in eine weiter verarbeitbare Form um. Standardmäßig gibt
es die von der PC-Funkuhr ausgelesene Zeit auf stdout aus. pcf77 muss
mitgeteilt werden, an welchem Druckerport die Uhr hängt. Man kann auch das
Programm mit der Option "-a" bitten, alle Druckerports abzuklappern. Wenn man
dann allerdings weiß, an welchem Port sich die Uhr befindet, ist die Angabe
des Ports auf der Kommandozeile sicherlich das bessere Vorgehen.

Als root kann man auch die Systemzeit nach der PC-Funkuhr stellen. Dabei gibt
es die Möglichkeit, ein sanftes Stellen der Zeit durchzuführen (Option -s,
falls Systemzeit um höchstens200 Sekunden von DCF77-Zeit
abweicht), um eine streng monoton wachsende Systemzeit zu realisieren. Gibt
man die Option -S an, wird auf jeden Fall die Systemzeit nach der DCF77-Zeit
gestellt. (-t bzw. -T tun das gleiche, sollte die Funkuhr jedoch das letzte
Mal kein Signal empfangen haben, dann wird auf das Stellen der Systemuhr
verzichtet. Das hat Vorteile, wenn die Quartzuhr in der PC-Funkuhr zu ungenau
geht.)

Ich habe versucht, eine rudimentäre Qualitätskontrolle einzubauen. Leider
kenne ich das DCF77 Signalprotokoll, das zu diesem Zwecke ausgelesen werden
muss, zu wenig, um sicher zu sein, dass hier kein Unfug gemessen wird. Das
Ergebnis ist allerdings ähnlich wie bei der Original-SW unter DOS. Die Ausgabe
auf das Terminal mag etwas simpel erscheinen, erfüllt aber ihren Zweck!

Hier der Vollständigkeit halber noch das usage des Programms:

usage: pcf77 [options] [+FORMAT]
   reads timer information of DCF77-Clock ("PC-Funkuhr") at printer port,
   needs an appropriate patched lp-kernel-module.
   See date(1) for a description of the FORMAT-string.
options:
   -a       : autoprobe lp devices
   -c       : check quality of DCF77 radio signal
   -D       : print out difference between system and DCF time
   -h, -?   : prints this usage-message
   -m       : mail problems with the "PC-Funkuhr" to addr
   -p       : Printer Port (default: /dev/lp1)
   -q       : quiet, don't print time read from clock
   -s       : set system clock "smoothly",
              if time-difference is less than 20 seconds
   -S       : set system clock immediately
   -t       : same as -s, don't set time if "PC-Funkuhr"
              had problems receiving radio signal
   -T       : same as -S, don't set time if "PC-Funkuhr"
              had problems receiving radio signal
   -v       : print version and exit


Vorsicht
--------
Ich kann natürlich nicht garantieren, dass nicht irgendein Teil der
Hardware (Rechner, PC-Funkuhr, Drucker) Schaden durch die Anwendung der
Programme nimmt. Jeder, der das Programm pcf77 und die benötigten
kernel-patches einsetzt, tut dies auf eigenes Risiko!



Installation
------------
Die Installation erfolgt am besten als root.

1. Package auspacken in [destdir]

2. Kernel patchen.  Dazu in das Linux-Source Verzeichnis (bei mir ist 
das /usr/src/linux) wechseln, das hoffentlich nicht allzusehr von den
getesteten Kernelversionen abweicht. Dort: 
patch -p0 < [destdir]/pcf77-0.9.2/pcf77.linux-2.6.8.diff
(Kernel >=2.2.5:) make config (PCF Support auswählen, lp als Modul kompilieren)
make modules
make modules_install

Der Printer-Driver sollte als Modul kompiliert werden, damit der
kernel nicht komplett neu erstellt werden muss.

3. cd [destdir]/pcf77-0.9.2
(evtl. in pcf77.h den Wert von STDPORT anpassen)
make
(falls LPPCFTIMER nicht definiert wurde, muss man
/usr/src/linux/include/lp.h nach /usr/include/linux/lp.h kopieren!)

Austesten mit "./pcf77 -p portname" - bitte beachten, dass die
Druckerports für den User les-/schreibbar sind; wenn ok, dann:

make install
make install_man

4. Soll die PC-Funkuhr beim Starten des Rechners ausgelesen werden, dann muss
die Datei /etc/rc.d/boot modifiziert werden (S.u.S.E, bei anderen
Distributionen suche man in den rc-Files nach den Programmzeilen, die die
Hardware-Uhr des Rechners auslesen.) Folgende drei Zeilen ergänze man in boot
(NACH den vorhandenen hardware-clock Angaben! port ggf. anpassen!):
# read DCF clock and set system and hardware clock, send mail to root
/usr/local/bin/pcf77 -q -S -p /dev/lp2 -m root
test $? -eq 0 && hwclock --systohc

5. Wer eine unpräzise Systemuhr hat, kann zukünftig für root einen cron-Job
einrichten, z.B. einmal am Tag oder wie hier stündlich (port anpassen!):
31 * * * *      /usr/bin/pcf77 -s -p /dev/lp2 -m root

6. Bei einem kernel mit parport-Treiber muss darauf geachtet werden, dass
dieser auch die richtigen Ports freigibt. Dazu muss evtl. in /etc/modules.conf
die Zeile "options parport...." angepasst werden.


Getestete Konfigurationen
-------------------------
Siehe Datei TESTED.

Known Bugs
----------
Ein Aufruf von pcf77 am Letzten eines Monats um 23:59:59 kann zu Fehlern beim
Setzen der Systemzeit führen.
Um die Zeitzone habe ich mir keinerlei Gedanken gemacht. Ich gehe davon aus,
dass außerhalb der ME(S)T die Geschichte nicht läuft!

Ein Jahr-2000 Problem kennt die Uhr, soweit ich weiß, nicht. Allerdings
übermittelt sie das Datum nur zweistellig, sodass man schon zwischen den
Jahrhunderten willkürlich unterscheiden muss. Ich habe mich entschlossen,
die Entscheidung, wann der Jahrhundertsprung stattfinden soll, durch eine
simple Variable im Programmcode festzulegen. Ihr Wert ist 90, sodass
Daten <90 in 'gelesenes Jahr + 2000', alles andere in 'gelesenes
Jahr + 1900' umgerechnet wird. Letztlich kann man durch einmaliges
Kompilieren des Programms pro Jahrhundert (:-)) diese Grenze immer wieder neu
festlegen.

Es gibt Konfigurationen, bei denen das Auslesen der Funkuhr nur bei
eingeschaltetem Drucker (z.B. EPL5200) funktioniert, oder aber nur dann, wenn
überhaupt kein Drucker angeschlossen ist. Dies scheint an der Verdrahtung der
Uhr zu liegen, bzw. am Protokoll zum Auslesen. Falls die Uhr unter DOS/Win
"fehlerfreier" ausgelesen werden kann als unter gleichen Umständen unter Linux
mit pcf77, so bitte ich um Rückmeldung.

Bis Version 0.7.1 gab es einen Fehler beim "sanften" Stellen der Systemuhr mit
der Option -s. Dank des Hinweises von Philippe aus Paris (auch dort
funktioniert die Uhr!) ist der Fehler behoben worden!

Rückmeldung
-----------
Falls diese kleine Programmsammlung wie gewünscht arbeitet, teilt mir dies
bitte kurz mit (in der Form wie oben unter "Getestete Konfigurationen"
angegeben); wenn nicht, so sollten wir erst recht in Kontakt treten und
versuchen, die SW auch unter anderer HW-Konfiguration als der meinen zum
Laufen zu bekommen.


Kontakt
-------
matthias@familie-schuetze.de
Falls jemand Änderungen am Code vornimmt (vornehmen muss), wäre ich um
Rückmeldung dankbar!


Copyright
---------
GPL



Viel Erfolg mit präziser Zeit,
             Matthias Schütze                            29 Mar 06