Blob Blame History Raw
From b56ba8f073c186339572b091033e1ebcd88191df Mon Sep 17 00:00:00 2001
From: Greg King <gregdk@users.sf.net>
Date: Fri, 27 Dec 2019 18:07:37 -0500
Subject: [PATCH 132/170] Added real-time clock functions to the cx16 library.

---
 libsrc/cx16/getres.s      | 36 +++++++++++++++++++
 libsrc/cx16/gettime.s     | 56 +++++++++++++++++++++++++++++
 libsrc/cx16/settime.s     | 55 +++++++++++++++++++++++++++++
 libsrc/cx16/status.s      | 16 ---------
 libsrc/cx16/tmcommon.s    | 40 +++++++++++++++++++++
 testcode/lib/clock-test.c | 74 ++++++++++++++++++++++-----------------
 6 files changed, 229 insertions(+), 48 deletions(-)
 create mode 100644 libsrc/cx16/getres.s
 create mode 100644 libsrc/cx16/gettime.s
 create mode 100644 libsrc/cx16/settime.s
 delete mode 100644 libsrc/cx16/status.s
 create mode 100644 libsrc/cx16/tmcommon.s

diff --git a/libsrc/cx16/getres.s b/libsrc/cx16/getres.s
new file mode 100644
index 00000000..dad23701
--- /dev/null
+++ b/libsrc/cx16/getres.s
@@ -0,0 +1,36 @@
+;
+; 2019-12-26, Greg King
+;
+; int __fastcall__ clock_getres (clockid_t clk_id, struct timespec *res);
+;
+
+        .include        "time.inc"
+
+        .importzp       ptr1
+        .import         incsp1, return0
+
+
+;----------------------------------------------------------------------------
+
+.proc   _clock_getres
+
+        sta     ptr1
+        stx     ptr1+1
+
+        ldy     #.sizeof(timespec) - 1
+@L1:    lda     time,y
+        sta     (ptr1),y
+        dey
+        bpl     @L1
+
+        jsr     incsp1
+        jmp     return0
+
+.endproc
+
+;----------------------------------------------------------------------------
+; timespec struct with tv_nsec set to approximately 1/60 of a second
+.rodata
+
+time:   .dword  0
+        .dword  17 * 1000 * 1000
diff --git a/libsrc/cx16/gettime.s b/libsrc/cx16/gettime.s
new file mode 100644
index 00000000..336b0f95
--- /dev/null
+++ b/libsrc/cx16/gettime.s
@@ -0,0 +1,56 @@
+;
+; 2019-12-27, Greg King
+;
+; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp);
+;
+
+        .include        "time.inc"
+        .include        "cx16.inc"
+
+        .import         pushax, pusheax, tosmul0ax, steaxspidx, incsp1, return0
+        .import         TM, load_jiffy
+        .import         CLOCK_GET_DATE_TIME
+
+
+;----------------------------------------------------------------------------
+
+.proc   _clock_gettime
+
+        jsr     pushax
+        jsr     pushax
+
+        jsr     CLOCK_GET_DATE_TIME
+
+        lda     gREG::r0L
+        sta     TM + tm::tm_year
+        lda     gREG::r0H
+        dec     a
+        sta     TM + tm::tm_mon
+        lda     gREG::r1L
+        sta     TM + tm::tm_mday
+
+        lda     gREG::r1H
+        sta     TM + tm::tm_hour
+        lda     gREG::r2L
+        sta     TM + tm::tm_min
+        lda     gREG::r2H
+        sta     TM + tm::tm_sec
+
+        lda     #<TM
+        ldx     #>TM
+        jsr     _mktime
+        ldy     #timespec::tv_sec
+        jsr     steaxspidx              ; Pops address pushed by 2. pushax
+
+        jsr     load_jiffy
+        jsr     pusheax
+        lda     gREG::r3L
+        ldx     #>$0000
+        jsr     tosmul0ax
+        ldy     #timespec::tv_nsec
+        jsr     steaxspidx              ; Pops address pushed by 1. pushax
+
+        jsr     incsp1
+        jmp     return0
+
+.endproc
diff --git a/libsrc/cx16/settime.s b/libsrc/cx16/settime.s
new file mode 100644
index 00000000..81749f50
--- /dev/null
+++ b/libsrc/cx16/settime.s
@@ -0,0 +1,55 @@
+;
+; 2019-12-27, Greg King
+;
+; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp);
+;
+
+        .include        "time.inc"
+        .include        "cx16.inc"
+
+        .importzp       ptr1
+        .import         pushax, pusheax, ldax0sp, ldeaxidx
+        .import         tosdiveax, incsp3, return0
+        .import         load_jiffy
+        .import         CLOCK_SET_DATE_TIME
+
+
+.macro  COPY    reg, offset
+        ldy     #offset
+        lda     (ptr1),y
+        sta     gREG::reg
+.endmac
+
+;----------------------------------------------------------------------------
+
+.proc   _clock_settime
+
+        jsr     pushax
+
+        .assert timespec::tv_sec = 0, error
+        jsr     _localtime
+        sta     ptr1
+        stx     ptr1+1
+
+        COPY    r0L, tm::tm_year
+        COPY    r0H, tm::tm_mon
+        inc     gREG::r0H
+        COPY    r1L, tm::tm_mday
+        COPY    r1H, tm::tm_hour
+        COPY    r2L, tm::tm_min
+        COPY    r2H, tm::tm_sec
+
+        jsr     ldax0sp                 ; Get tp
+        ldy     #timespec::tv_nsec+3
+        jsr     ldeaxidx                ; Get nanoseconds
+        jsr     pusheax
+        jsr     load_jiffy
+        jsr     tosdiveax
+        sta     gREG::r3L               ; Put number of jiffies
+
+        jsr     CLOCK_SET_DATE_TIME
+
+        jsr     incsp3
+        jmp     return0
+
+.endproc
diff --git a/libsrc/cx16/status.s b/libsrc/cx16/status.s
deleted file mode 100644
index e3446637..00000000
--- a/libsrc/cx16/status.s
+++ /dev/null
@@ -1,16 +0,0 @@
-;
-; 2019-11-05, Greg King
-;
-
-        .export         ST: zp
-
-.segment        "EXTZP": zp
-
-; This is a temporary hack.
-
-; A zero-page copy of the IEC status byte.
-; This is needed because the Commander X16's Kernal's status
-; variable was moved out of the zero page.  But, the common
-; CBM file function modules import this as a zero-page variable.
-
-ST:     .res    1
diff --git a/libsrc/cx16/tmcommon.s b/libsrc/cx16/tmcommon.s
new file mode 100644
index 00000000..0eed245d
--- /dev/null
+++ b/libsrc/cx16/tmcommon.s
@@ -0,0 +1,40 @@
+;
+; 2019-12-27, Greg King
+;
+; Common stuff for the clock routines
+;
+
+        .export         TM, load_jiffy
+
+        .importzp       sreg
+
+
+;----------------------------------------------------------------------------
+; Load .EAX with the approximate number of nanoseconds
+; in one jiffy (1/60th of a second).
+
+.proc   load_jiffy
+
+        lda     #<(17 * 1000 * 1000 / $10000)
+        ldx     #>(17 * 1000 * 1000 / $10000)
+        sta     sreg
+        stx     sreg+1
+        lda     #<(17 * 1000 * 1000)
+        ldx     #>(17 * 1000 * 1000)
+        rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; TM struct with "is daylight-saving time" set to "unknown"
+.data
+
+TM:     .word   0               ; tm_sec
+        .word   0               ; tm_min
+        .word   0               ; tm_hour
+        .word   0               ; tm_mday
+        .word   0               ; tm_mon
+        .word   0               ; tm_year
+        .word   0               ; tm_wday
+        .word   0               ; tm_yday
+        .word   .loword(-1)     ; tm_isdst
diff --git a/testcode/lib/clock-test.c b/testcode/lib/clock-test.c
index e3115d2f..ba4b69e4 100644
--- a/testcode/lib/clock-test.c
+++ b/testcode/lib/clock-test.c
@@ -1,7 +1,8 @@
-/* Clock test program
- *
- * 25-Sep-2018, chris@groessler.org
- */
+/* Calendar-clock test program
+**
+** 2018-Sep-25, chris@groessler.org
+** 2019-Dec-27, Greg King
+*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -10,74 +11,83 @@
 #include <errno.h>
 
 #ifdef __CC65__
-#include <conio.h>
-#include <cc65.h>
-#endif /* #ifdef __CC65__ */
+ #include <conio.h>
+ #include <cc65.h>
+#endif
 
-static void print_time(void)
+static int print_time(void)
 {
     struct tm *cur_tm;
     time_t cur_time = time(NULL);
+
     if (cur_time == -1) {
         printf("time() failed: %s\n", strerror(errno));
-        return;
+        return 1;
     }
     cur_tm = localtime(&cur_time);
 
     printf("time: %s\n", asctime(cur_tm));
     // DEBUG:
-    printf("mday=%d mon=%d year=%d\nhour=%d min=%d sec=%d\n", cur_tm->tm_mday, cur_tm->tm_mon, cur_tm->tm_year, cur_tm->tm_hour, cur_tm->tm_min, cur_tm->tm_sec);
+    printf("year=%d, mon=%d, mday=%d\nhour=%d, min=%d, sec=%d\n",
+           cur_tm->tm_year, cur_tm->tm_mon, cur_tm->tm_mday,
+           cur_tm->tm_hour, cur_tm->tm_min, cur_tm->tm_sec);
+    return 0;
 }
 
 int main(int argc, char **argv)
 {
-    char c = 0;
+    char c;
     int s;
     struct tm cur_time;
     struct timespec new_time;
 
 #ifdef __CC65__
-    /* if DOS will automatically clear the screen after the program exits, wait for a keypress... */
+    /* If DOS automatically will clear the screen after the program exits,
+    ** then wait for a key-press.
+    */
     if (doesclrscrafterexit())
         atexit((void (*)(void))cgetc);
 #endif
 
-    if (argc <= 1) {
-        print_time();
-        return 0;
+    if (argc == 1) {
+        return print_time();
     }
 
-    if (argc != 3 || strcasecmp(*(argv + 1), "set")) {
-        printf("usage: CLOCKTST [set DD-MM-YY-HH-MM-SS]\n");
+    if (argc != 2) {
+#ifdef __CC65__
+        printf("Usage: run:rem [YY-MM-DD-HH-MM-SS]\n");
+#else
+        printf("Usage: %s [YY-MM-DD-HH-MM-SS]\n", argv[0]);
+#endif
         return 1;
     }
 
-    memset(&cur_time, 0, sizeof(cur_time));
-    s = sscanf(*(argv + 2), "%d-%d-%d-%d-%d-%d", &cur_time.tm_mday, &cur_time.tm_mon, &cur_time.tm_year, &cur_time.tm_hour, &cur_time.tm_min, &cur_time.tm_sec);
-    if (s != 6 || cur_time.tm_year > 99 /* other input values aren't being verified... */) {
-        printf("invalid time/date format\n");
+    memset(&cur_time, 0, sizeof cur_time);
+    s = sscanf(argv[1], "%d-%d-%d-%d-%d-%d",
+               &cur_time.tm_year, &cur_time.tm_mon, &cur_time.tm_mday,
+               &cur_time.tm_hour, &cur_time.tm_min, &cur_time.tm_sec);
+    if (s != 6 || cur_time.tm_year > 99 /* other input values aren't being verified */) {
+        printf("Invalid date-time format\n");
         return 1;
     }
+    cur_time.tm_year += 100;            /* assume 21st century */
     --cur_time.tm_mon;
-    if (cur_time.tm_year < 79)
-        cur_time.tm_year += 100;  /* adjust century */
 
-    memset(&new_time, 0, sizeof(new_time));
+    memset(&new_time, 0, sizeof new_time);
     new_time.tv_sec = mktime(&cur_time);
 
-    printf("\nyou are about to set the time to\n-->  %s\n\nContinue (y/n)?", ctime(&new_time.tv_sec));
-
-    while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
+    printf("\nYou are about to set the time to\n-->  %s\nContinue (y/n)? ", ctime(&new_time.tv_sec));
+    do {
 #ifdef __CC65__
         c = cgetc();
 #else
         c = getchar();
 #endif
-    }
+    } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
     printf("%c\n", c);
 
     if (c == 'n' || c == 'N') {
-        printf("user abort\n");
+        printf("User abort\n");
         return 0;
     }
 
@@ -86,11 +96,11 @@ int main(int argc, char **argv)
         printf("clock_settime() failed: %s\n", strerror(errno));
         return 1;
     }
-    printf("time set!\n");
+    printf("Time set!\n\n");
+
     //DEBUG test begin
-    print_time();
+    return print_time();
     //DEBUG test end
-    return 0;
 }
 /* Local Variables: */
 /* c-file-style: "cpg" */
-- 
2.26.0