From b56ba8f073c186339572b091033e1ebcd88191df Mon Sep 17 00:00:00 2001 From: Greg King Date: Fri, 27 Dec 2019 18:07:37 -0500 Subject: [PATCH] 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 000000000..dad237014 --- /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 000000000..336b0f957 --- /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 + 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 000000000..81749f508 --- /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 e3446637d..000000000 --- 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 000000000..0eed245dc --- /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 e3115d2f1..ba4b69e42 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 #include @@ -10,74 +11,83 @@ #include #ifdef __CC65__ -#include -#include -#endif /* #ifdef __CC65__ */ + #include + #include +#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" */