diff options
| author | user <user@clank> | 2026-09-24 23:08:54 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-24 23:08:54 +0200 |
| commit | be1a8f74e48d4ed2ae3a0b78a7137b4bc41a2969 (patch) | |
| tree | 25477cc16331b6e919deab918eecfcc4edebc0cb /usr/date.c | |
| parent | usr: sort, cmp, strings, du, time (diff) | |
| download | gbos-master.tar.gz gbos-master.tar.xz gbos-master.zip | |
An MBC5 cart has no RTC, so SNTP is the only route to a wall clock. ntpdate
does one 48-byte UDP exchange on port 123 and hands the stamp to the kernel;
SYS_SETTIME keeps it with the tick it arrived at, and SYS_GETTIME adds the
elapsed ticks back, so date(1) is just formatting.
/# ntpdate
ntpdate: clock set from pool.ntp.org
/# date
Sep 24 21:01:23 UTC 2026 (host said 21:01:26)
The clock does not survive a power cycle - which is exactly what /rc is for:
`ntpdate` there and the machine boots knowing the time.
All of it is bounded subtraction, no long division or shifts: SDCC pulls those
from sm83.lib, whose modules link into the $A000 RAM window. The month tables
are string literals for the same family of reason - an initialized array goes
to _INITIALIZED at $A000 and the image overflows its bank ("buffer too small"
out of makebin), which is how this first failed to link.
Diffstat (limited to 'usr/date.c')
| -rw-r--r-- | usr/date.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/usr/date.c b/usr/date.c new file mode 100644 index 0000000..57108ab --- /dev/null +++ b/usr/date.c @@ -0,0 +1,87 @@ +#include "gbos.h" +/* date: print the wall clock, UTC. + * + * The kernel hands back unix seconds (SYS_GETTIME); turning that into a date + * is all bounded subtraction - no long division or shifts, which SDCC would + * pull out of sm83.lib and link into the $A000 RAM window (see usr/uptime.c + * and usr/build.sh). ~20k rounds for the day loop is a fraction of a second. + * + * Says so plainly when the clock has never been set: run ntpdate first. */ + +/* No initialized arrays: SDCC puts those in _INITIALIZED at $A000, the RAM + window, and the image then overflows its bank ("buffer too small" out of + makebin - see usr/ansi.c and usr/build.sh). String literals live in _CODE, + so the tables are literals indexed by hand. */ +#define MDAYS "\x1f\x1c\x1f\x1e\x1f\x1e\x1f\x1f\x1e\x1f\x1e\x1f" +#define MNAME "JanFebMarAprMayJunJulAugSepOctNovDec" + +static void two(unsigned int v) { + if (v < 10) putc('0'); + putu(v); +} +static unsigned char leap(unsigned int y) { + if (y & 3) return 0; + if (y == 2100) return 0; /* good enough until then */ + return 1; +} + +void main(void) { + unsigned char t[4]; + union { + unsigned long l; + unsigned char b[4]; + } u; + unsigned long sec; + unsigned int days = 0, year = 1970, h, m, i, dim; + + if (!gettime(t)) { + puts("date: clock not set (run ntpdate)"); + nl(); + sexit(1); + } + u.b[0] = t[0]; + u.b[1] = t[1]; + u.b[2] = t[2]; + u.b[3] = t[3]; + sec = u.l; + + while (sec >= 86400UL) { + sec -= 86400UL; + days++; + } + h = 0; + while (sec >= 3600UL) { + sec -= 3600UL; + h++; + } + m = 0; + while (sec >= 60UL) { + sec -= 60UL; + m++; + } + + for (;;) { /* years, then months */ + unsigned int len = leap(year) ? 366 : 365; + if (days < len) break; + days -= len; + year++; + } + for (i = 0; i < 12; i++) { + dim = (unsigned char)MDAYS[i]; + if (i == 1 && leap(year)) dim = 29; + if (days < dim) break; + days -= dim; + } + writes(MNAME + i * 3, 3); + putc(' '); + putu(days + 1); + putc(' '); + two(h); + putc(':'); + two(m); + putc(':'); + two((unsigned int)sec); + puts(" UTC "); + putu(year); + nl(); +} |
