Created
June 13, 2025 18:00
-
-
Save theodric/5f311fa61c869bed096a68b19063fc5c to your computer and use it in GitHub Desktop.
"Source to access the HKW PC - Funkuhr under Unix" - saved from a lost webpage: http://www.hello-penguin.com/software/hkw.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This program shows how to access the HKW PC - Funkuhr. | |
* The receiver is also supported by xntpd. | |
* (c) 1996 by St. Traby, GPL | |
*/ | |
#include <stdio.h> | |
#include <termios.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#include <signal.h> | |
void | |
sighandler (int sig) | |
{ | |
fprintf (stderr, "signal exit, signum=%d\n", sig); | |
_exit (1); | |
} | |
static void | |
sleep_10ms (void) | |
{ | |
struct timeval tv; | |
tv.tv_sec = 0; | |
tv.tv_usec = 10000; | |
select (0, NULL, NULL, NULL, &tv); | |
} | |
static int | |
writeclock (int fd, const char *msg) | |
{ | |
const char *x = msg; | |
int err = 0; | |
char y[22]; | |
errno = 0; | |
while (!errno && *x) { | |
if (write (fd, x, 1) != 1) { | |
return x - msg; | |
} | |
read (fd, y, 1); | |
sleep_10ms (); | |
x++; | |
} | |
return x - msg - 1; | |
} | |
static int | |
readclock (int fd, char *buf) | |
{ | |
char *p = buf; | |
errno = 0; | |
do { | |
read (fd, p, 1); | |
} while (!errno && *p++ != '\r'); | |
return p - buf; | |
} | |
static int | |
openclock (const char *dev) | |
{ | |
int fd; | |
struct termios t; | |
fd = open (dev, O_RDWR); | |
if (fd == -1) { | |
fprintf (stderr, "open of \"%s\" failed, %m\n", dev); | |
return fd; | |
} | |
t.c_iflag = IGNBRK | ISTRIP; | |
t.c_oflag = 0; | |
t.c_cflag = B300 | CS8 | CREAD | CLOCAL | CSTOPB; | |
t.c_lflag = 0; | |
t.c_cc[VMIN] = 1; | |
t.c_cc[VTIME] = 0; | |
if (tcsetattr (fd, TCSANOW, &t) == -1) { | |
fprintf (stderr, "tcsetattr failed, %m\n", dev); | |
close (fd); | |
return -1; | |
} | |
return fd; | |
} | |
#define CHECK10(x) ((x) >= '0' && (x) <= '9') | |
#define CHECK5(x) ((x) >= '0' && (x) <= '5') | |
#define CHECK3(x) ((x) >= '0' && (x) <= '3') | |
#define CHECK2(x) ((x) >= '0' && (x) <= '2') | |
#define CHECK1(x) ((x) >= '0' && (x) <= '1') | |
#define CHECKW(x) ((x) >= '1' && (x) <= '7') | |
#define CHECK_UTC(x) 1 | |
#define CHECK_STATUS(x) ((x) & 1) | |
static int | |
check_valid (const char *t) | |
{ | |
if (CHECK2 (t[0]) && CHECK10 (t[1]) && CHECK5 (t[2]) && CHECK10 (t[3]) | |
&& CHECK5 (t[4]) && CHECK10 (t[5]) && CHECKW (t[6]) | |
&& CHECK3 (t[7]) && CHECK10 (t[8]) && CHECK1 (t[9]) | |
&& CHECK10 (t[10]) && CHECK10 (t[11]) && CHECK10 (t[12]) | |
&& CHECK_UTC (t[13]) && CHECK_STATUS (t[14]) && t[15] == '\r') | |
return 1; | |
return 0; | |
} | |
static char *weekdays[] = { "Monday", | |
"Tuesday", | |
"Wednestay", | |
"Thurstay", | |
"Saturday", | |
"Sunday" | |
}; | |
static int | |
display_result (const char *t) | |
{ | |
int res; | |
fprintf (stdout, "Time: %c%c:%c%c:%c%c\n", t[0], t[1], t[2], t[3], | |
t[4], t[5]); | |
fprintf (stdout, "Date: %s 20%c%c-%c%c-%c%c\n", | |
(t[6] >= '1' | |
&& t[6] < '8') ? weekdays[t[6] - '0' - 1] : "unknown", | |
t[11], t[12], t[9], t[10], t[7], t[8]); | |
fprintf (stdout, "Time format: %s\n", (t[13] & 0x4) ? "UTC" : "MET"); | |
fprintf (stdout, "Low Battery: %s\n", (t[14] & 0x8) ? "yes" : "no"); | |
fprintf (stderr, "Valid-Bit : information is %svalid\n", | |
(t[15] && 1) ? "" : "in"); | |
res = check_valid (t); | |
fprintf (stderr, "Check-ok : information looks %s\n", | |
(res) ? "ok" : "bad"); | |
return 1 - res; | |
} | |
int | |
main () | |
{ | |
int fd, rc; | |
char ret[255]; | |
signal (SIGALRM, sighandler); | |
fd = openclock ("/dev/ttyS1"); | |
if (fd < 0) | |
return 1; | |
alarm (3); | |
writeclock (fd, "o\r"); | |
rc = readclock (fd, ret); | |
alarm (0); | |
if (rc != 16) { | |
fprintf (stderr, "expected 16 bytes, got %d\n", rc); | |
return 1; | |
} | |
return display_result (ret); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment