aboutsummaryrefslogtreecommitdiffstats
path: root/usr/uptime.c
blob: 10622173724a099f6a0e0e077c2bef544b013bc1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "gbos.h"
/* uptime: time since boot, from the kernel's 64 Hz tick (SYS_UPTIME).

   No long division/shifts: SDCC pulls those from sm83.lib, whose modules
   link into their own areas that land in the $A000 RAM window (see
   usr/build.sh). Everything here is inlined 8/32-bit add/sub/compare:
   ticks>>6 done bytewise, then day/hour/minute by bounded subtraction. */

static void two(unsigned int v) {       /* zero-padded 2-digit field */
    if (v < 10) putc('0');
    putu(v);
}

void main(void) {
    unsigned char t[4];
    union { unsigned long l; unsigned char b[4]; } u;  /* sm83 is LE */
    unsigned long sec;
    unsigned int d, h, m;

    gticks(t);                          /* 32-bit LE tick count, 64 Hz */

    /* seconds = ticks >> 6, composed a byte at a time (24 bits is 194 days) */
    u.b[0] = (unsigned char)((t[0] >> 6) | (t[1] << 2));
    u.b[1] = (unsigned char)((t[1] >> 6) | (t[2] << 2));
    u.b[2] = (unsigned char)((t[2] >> 6) | (t[3] << 2));
    u.b[3] = 0;
    sec = u.l;

    d = 0;
    while (sec >= 86400UL) { sec -= 86400UL; d++; }   /* <= 194 rounds */
    h = 0;
    while (sec >= 3600UL)  { sec -= 3600UL;  h++; }   /* <= 23 rounds  */
    m = 0;
    while (sec >= 60UL)    { sec -= 60UL;    m++; }   /* <= 59 rounds  */

    puts("up ");
    if (d) { putu(d); puts("d "); }
    putu(h); putc(':'); two(m); putc(':'); two((unsigned int)sec);
    nl();
}