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