The CIA TOD only stores the time but not the date. Therefore the date set by clock_settime() ist just stored inside the C library for retrieval via clock_gettime().
The "very special" handling of 12AM/PM is based on https://groups.google.com/d/msg/comp.sys.cbm/ysVYSX4AMbc/vHrXCWEhCOUJ saying:
==========
24hr: Wr => Rd => Nx
--------------------
0 : 92 => 12 => 01 <= Switch from 00 to 01 (24-hour notation)
1 : 01 => 01 => 02
2 : 02 => 02 => 03
11 : 11 => 11 => 92
12 : 12 => 92 => 81 <= Switch from 12 to 13 (24-hour notation)
13 : 81 => 81 => 82
14 : 82 => 82 => 83
23 : 91 => 91 => 12
1. column ("24hr"): hour to be tested (decimal)
2. column ("Wr"): hour written to TOD register (BCD)
3. column ("Rd"): hour read from TOD register (BCD) immediately after writing the value in column 2 to see the conversion between AM/PM, if any
4. column ("Nx"): next hour (BCD) after the hour switch
==========
Thanks Paul!
.include "time.inc"
.include "c128.inc"
- .include "get_tv.inc"
- .constructor inittime
.importzp sreg, tmp1, tmp2
.import pushax, pusheax, tosmul0ax, steaxspidx, incsp1, return0
- .import _get_tv
+ .import TM, load_tenth
;----------------------------------------------------------------------------
ldy #timespec::tv_sec
jsr steaxspidx ; Pops address pushed by 2. pushax
- lda #<(100 * 1000 * 1000 / $10000)
- ldx #>(100 * 1000 * 1000 / $10000)
- sta sreg
- stx sreg+1
- lda #<(100 * 1000 * 1000)
- ldx #>(100 * 1000 * 1000)
+ jsr load_tenth
jsr pusheax
lda CIA1_TOD10
ldx #>$0000
rts
.endproc
-
-;----------------------------------------------------------------------------
-; Constructor that writes to the 1/10 sec register of the TOD to kick it
-; into action. If this is not done, the clock hangs. We will read the register
-; and write it again, ignoring a possible change in between.
-.segment "ONCE"
-
-.proc inittime
-
- lda CIA1_TOD10
- sta CIA1_TOD10
- jsr _get_tv
- cmp #TV::PAL
- bne @60Hz
- lda CIA1_CRA
- ora #$80
- sta CIA1_CRA
-@60Hz: rts
-
-.endproc
-
-;----------------------------------------------------------------------------
-; TM struct with date set to 1970-01-01
-.data
-
-TM: .word 0 ; tm_sec
- .word 0 ; tm_min
- .word 0 ; tm_hour
- .word 1 ; tm_mday
- .word 0 ; tm_mon
- .word 70 ; tm_year
- .word 0 ; tm_wday
- .word 0 ; tm_yday
- .word 0 ; tm_isdst
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; int clock_settime (clockid_t clk_id, const struct timespec *tp);
+;
+
+ .include "time.inc"
+ .include "c128.inc"
+
+ .importzp sreg, ptr1
+ .import pushax, pusheax, ldax0sp, ldeaxidx
+ .import tosdiveax, incsp3, return0
+ .import TM, load_tenth
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc _clock_settime
+
+ jsr pushax
+
+ jsr _localtime
+ sta ptr1
+ stx ptr1+1
+ ldy #.sizeof(tm)-1
+@L1: lda (ptr1),y
+ sta TM,y
+ dey
+ bpl @L1
+
+ lda TM + tm::tm_hour
+ jsr dec2BCD
+ tax ; Force flags
+ bne @L2
+ lda #$92 ; 12 AM
+ bne @L3
+@L2: cmp #$13 ; 1 PM
+ bcc @L3
+ sed
+ sbc #$12
+ cld
+ ora #%10000000
+@L3: sta CIA1_TODHR
+ lda TM + tm::tm_min
+ jsr dec2BCD
+ sta CIA1_TODMIN
+ lda TM + tm::tm_sec
+ jsr dec2BCD
+ sta CIA1_TODSEC
+
+ jsr ldax0sp
+ ldy #3+timespec::tv_nsec
+ jsr ldeaxidx
+ jsr pusheax
+ jsr load_tenth
+ jsr tosdiveax
+ sta CIA1_TOD10
+
+ jsr incsp3
+ jmp return0
+
+.endproc
+
+;----------------------------------------------------------------------------
+; Just sum up the value in BCD mode.
+; http://forum.6502.org/viewtopic.php?p=7629#p7629
+
+.proc dec2BCD
+
+ tax
+ dex
+ bmi @L9
+ lda #0
+ clc
+ sed
+@L1: adc #1
+ dex
+ bpl @L1
+ cld
+@L9: rts
+
+.endproc
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; Common stuff for the clock routines
+;
+
+ .include "c128.inc"
+ .include "get_tv.inc"
+
+ .export TM, load_tenth
+
+ .constructor inittime
+ .importzp sreg
+ .import _get_tv
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc load_tenth
+
+ lda #<(100 * 1000 * 1000 / $10000)
+ ldx #>(100 * 1000 * 1000 / $10000)
+ sta sreg
+ stx sreg+1
+ lda #<(100 * 1000 * 1000)
+ ldx #>(100 * 1000 * 1000)
+ rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; Constructor that writes to the 1/10 sec register of the TOD to kick it
+; into action. If this is not done, the clock hangs. We will read the register
+; and write it again, ignoring a possible change in between.
+.segment "ONCE"
+
+.proc inittime
+
+ lda CIA1_TOD10
+ sta CIA1_TOD10
+ jsr _get_tv
+ cmp #TV::PAL
+ bne @60Hz
+ lda CIA1_CRA
+ ora #$80
+ sta CIA1_CRA
+@60Hz: rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; TM struct with date set to 1970-01-01
+.data
+
+TM: .word 0 ; tm_sec
+ .word 0 ; tm_min
+ .word 0 ; tm_hour
+ .word 1 ; tm_mday
+ .word 0 ; tm_mon
+ .word 70 ; tm_year
+ .word 0 ; tm_wday
+ .word 0 ; tm_yday
+ .word 0 ; tm_isdst
.include "time.inc"
.include "c64.inc"
- .include "get_tv.inc"
- .constructor inittime
.importzp sreg, tmp1, tmp2
.import pushax, pusheax, tosmul0ax, steaxspidx, incsp1, return0
- .import _get_tv, _get_ostype
+ .import TM, load_tenth
;----------------------------------------------------------------------------
ldy #timespec::tv_sec
jsr steaxspidx ; Pops address pushed by 2. pushax
- lda #<(100 * 1000 * 1000 / $10000)
- ldx #>(100 * 1000 * 1000 / $10000)
- sta sreg
- stx sreg+1
- lda #<(100 * 1000 * 1000)
- ldx #>(100 * 1000 * 1000)
+ jsr load_tenth
jsr pusheax
lda CIA1_TOD10
ldx #>$0000
rts
.endproc
-
-;----------------------------------------------------------------------------
-; Constructor that writes to the 1/10 sec register of the TOD to kick it
-; into action. If this is not done, the clock hangs. We will read the register
-; and write it again, ignoring a possible change in between.
-.segment "ONCE"
-
-.proc inittime
-
- lda CIA1_TOD10
- sta CIA1_TOD10
- jsr _get_tv
- cmp #TV::PAL
- bne @60Hz
- jsr _get_ostype
- cmp #$43
- beq @60Hz
- lda CIA1_CRA
- ora #$80
- sta CIA1_CRA
-@60Hz: rts
-
-.endproc
-
-;----------------------------------------------------------------------------
-; TM struct with date set to 1970-01-01
-.data
-
-TM: .word 0 ; tm_sec
- .word 0 ; tm_min
- .word 0 ; tm_hour
- .word 1 ; tm_mday
- .word 0 ; tm_mon
- .word 70 ; tm_year
- .word 0 ; tm_wday
- .word 0 ; tm_yday
- .word 0 ; tm_isdst
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; int clock_settime (clockid_t clk_id, const struct timespec *tp);
+;
+
+ .include "time.inc"
+ .include "c64.inc"
+
+ .importzp sreg, ptr1
+ .import pushax, pusheax, ldax0sp, ldeaxidx
+ .import tosdiveax, incsp3, return0
+ .import TM, load_tenth
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc _clock_settime
+
+ jsr pushax
+
+ jsr _localtime
+ sta ptr1
+ stx ptr1+1
+ ldy #.sizeof(tm)-1
+@L1: lda (ptr1),y
+ sta TM,y
+ dey
+ bpl @L1
+
+ lda TM + tm::tm_hour
+ jsr dec2BCD
+ tax ; Force flags
+ bne @L2
+ lda #$92 ; 12 AM
+ bne @L3
+@L2: cmp #$13 ; 1 PM
+ bcc @L3
+ sed
+ sbc #$12
+ cld
+ ora #%10000000
+@L3: sta CIA1_TODHR
+ lda TM + tm::tm_min
+ jsr dec2BCD
+ sta CIA1_TODMIN
+ lda TM + tm::tm_sec
+ jsr dec2BCD
+ sta CIA1_TODSEC
+
+ jsr ldax0sp
+ ldy #3+timespec::tv_nsec
+ jsr ldeaxidx
+ jsr pusheax
+ jsr load_tenth
+ jsr tosdiveax
+ sta CIA1_TOD10
+
+ jsr incsp3
+ jmp return0
+
+.endproc
+
+;----------------------------------------------------------------------------
+; Just sum up the value in BCD mode.
+; http://forum.6502.org/viewtopic.php?p=7629#p7629
+
+.proc dec2BCD
+
+ tax
+ dex
+ bmi @L9
+ lda #0
+ clc
+ sed
+@L1: adc #1
+ dex
+ bpl @L1
+ cld
+@L9: rts
+
+.endproc
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; Common stuff for the clock routines
+;
+
+ .include "c64.inc"
+ .include "get_tv.inc"
+
+ .export TM, load_tenth
+
+ .constructor inittime
+ .importzp sreg
+ .import _get_tv, _get_ostype
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc load_tenth
+
+ lda #<(100 * 1000 * 1000 / $10000)
+ ldx #>(100 * 1000 * 1000 / $10000)
+ sta sreg
+ stx sreg+1
+ lda #<(100 * 1000 * 1000)
+ ldx #>(100 * 1000 * 1000)
+ rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; Constructor that writes to the 1/10 sec register of the TOD to kick it
+; into action. If this is not done, the clock hangs. We will read the register
+; and write it again, ignoring a possible change in between.
+.segment "ONCE"
+
+.proc inittime
+
+ lda CIA1_TOD10
+ sta CIA1_TOD10
+ jsr _get_tv
+ cmp #TV::PAL
+ bne @60Hz
+ jsr _get_ostype
+ cmp #$43
+ beq @60Hz
+ lda CIA1_CRA
+ ora #$80
+ sta CIA1_CRA
+@60Hz: rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; TM struct with date set to 1970-01-01
+.data
+
+TM: .word 0 ; tm_sec
+ .word 0 ; tm_min
+ .word 0 ; tm_hour
+ .word 1 ; tm_mday
+ .word 0 ; tm_mon
+ .word 70 ; tm_year
+ .word 0 ; tm_wday
+ .word 0 ; tm_yday
+ .word 0 ; tm_isdst
.import pushax, pusheax, tosmul0ax, steaxspidx, incsp1
.import sys_bank, restore_bank
+ .import TM, load_tenth
.importzp sreg, tmp1, tmp2
ldy #timespec::tv_sec
jsr steaxspidx ; Pops address pushed by 2. pushax
- lda #<(100 * 1000 * 1000 / $10000)
- ldx #>(100 * 1000 * 1000 / $10000)
- sta sreg
- stx sreg+1
- lda #<(100 * 1000 * 1000)
- ldx #>(100 * 1000 * 1000)
+ jsr load_tenth
jsr pusheax
ldy #CIA::TOD10
lda (cia2),y
rts
.endproc
-
-;----------------------------------------------------------------------------
-; TM struct with date set to 1970-01-01
-.data
-
-TM: .word 0 ; tm_sec
- .word 0 ; tm_min
- .word 0 ; tm_hour
- .word 1 ; tm_mday
- .word 0 ; tm_mon
- .word 70 ; tm_year
- .word 0 ; tm_wday
- .word 0 ; tm_yday
- .word 0 ; tm_isdst
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; int clock_settime (clockid_t clk_id, const struct timespec *tp);
+;
+
+ .include "time.inc"
+ .include "cbm510.inc"
+ .include "extzp.inc"
+
+ .importzp sreg, ptr1
+ .import pushax, pusheax, ldax0sp, ldeaxidx
+ .import sys_bank, restore_bank
+ .import tosdiveax, incsp3, return0
+ .import TM, load_tenth
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc _clock_settime
+
+ jsr sys_bank
+ jsr pushax
+
+ jsr _localtime
+ sta ptr1
+ stx ptr1+1
+ ldy #.sizeof(tm)-1
+@L1: lda (ptr1),y
+ sta TM,y
+ dey
+ bpl @L1
+
+ lda TM + tm::tm_hour
+ jsr dec2BCD
+ tax ; Force flags
+ bne @L2
+ lda #$92 ; 12 AM
+ bne @L3
+@L2: cmp #$13 ; 1 PM
+ bcc @L3
+ sed
+ sbc #$12
+ cld
+ ora #%10000000
+@L3: ldy #CIA::TODHR
+ sta (cia2),y
+ lda TM + tm::tm_min
+ jsr dec2BCD
+ ldy #CIA::TODMIN
+ sta (cia2),y
+ lda TM + tm::tm_sec
+ jsr dec2BCD
+ ldy #CIA::TODSEC
+ sta (cia2),y
+
+ jsr ldax0sp
+ ldy #3+timespec::tv_nsec
+ jsr ldeaxidx
+ jsr pusheax
+ jsr load_tenth
+ jsr tosdiveax
+ ldy #CIA::TOD10
+ sta (cia2),y
+
+ jsr incsp3
+
+ lda #0
+ tax
+ jmp restore_bank
+
+.endproc
+
+;----------------------------------------------------------------------------
+; Just sum up the value in BCD mode.
+; http://forum.6502.org/viewtopic.php?p=7629#p7629
+
+.proc dec2BCD
+
+ tax
+ dex
+ bmi @L9
+ lda #0
+ clc
+ sed
+@L1: adc #1
+ dex
+ bpl @L1
+ cld
+@L9: rts
+
+.endproc
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; Common stuff for the clock routines
+;
+
+ .include "cbm510.inc"
+
+ .export TM, load_tenth
+
+ .importzp sreg
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc load_tenth
+
+ lda #<(100 * 1000 * 1000 / $10000)
+ ldx #>(100 * 1000 * 1000 / $10000)
+ sta sreg
+ stx sreg+1
+ lda #<(100 * 1000 * 1000)
+ ldx #>(100 * 1000 * 1000)
+ rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; TM struct with date set to 1970-01-01
+.data
+
+TM: .word 0 ; tm_sec
+ .word 0 ; tm_min
+ .word 0 ; tm_hour
+ .word 1 ; tm_mday
+ .word 0 ; tm_mon
+ .word 70 ; tm_year
+ .word 0 ; tm_wday
+ .word 0 ; tm_yday
+ .word 0 ; tm_isdst
.import pushax, pusheax, tosmul0ax, steaxspidx, incsp1
.import sys_bank, restore_bank
+ .import TM, load_tenth
.importzp sreg, tmp1, tmp2
ldy #timespec::tv_sec
jsr steaxspidx ; Pops address pushed by 2. pushax
- lda #<(100 * 1000 * 1000 / $10000)
- ldx #>(100 * 1000 * 1000 / $10000)
- sta sreg
- stx sreg+1
- lda #<(100 * 1000 * 1000)
- ldx #>(100 * 1000 * 1000)
+ jsr load_tenth
jsr pusheax
ldy #CIA::TOD10
lda (cia),y
rts
.endproc
-
-;----------------------------------------------------------------------------
-; TM struct with date set to 1970-01-01
-.data
-
-TM: .word 0 ; tm_sec
- .word 0 ; tm_min
- .word 0 ; tm_hour
- .word 1 ; tm_mday
- .word 0 ; tm_mon
- .word 70 ; tm_year
- .word 0 ; tm_wday
- .word 0 ; tm_yday
- .word 0 ; tm_isdst
-
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; int clock_settime (clockid_t clk_id, const struct timespec *tp);
+;
+
+ .include "time.inc"
+ .include "cbm610.inc"
+ .include "extzp.inc"
+
+ .importzp sreg, ptr1
+ .import pushax, pusheax, ldax0sp, ldeaxidx
+ .import sys_bank, restore_bank
+ .import tosdiveax, incsp3, return0
+ .import TM, load_tenth
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc _clock_settime
+
+ jsr sys_bank
+ jsr pushax
+
+ jsr _localtime
+ sta ptr1
+ stx ptr1+1
+ ldy #.sizeof(tm)-1
+@L1: lda (ptr1),y
+ sta TM,y
+ dey
+ bpl @L1
+
+ lda TM + tm::tm_hour
+ jsr dec2BCD
+ tax ; Force flags
+ bne @L2
+ lda #$92 ; 12 AM
+ bne @L3
+@L2: cmp #$13 ; 1 PM
+ bcc @L3
+ sed
+ sbc #$12
+ cld
+ ora #%10000000
+@L3: ldy #CIA::TODHR
+ sta (cia),y
+ lda TM + tm::tm_min
+ jsr dec2BCD
+ ldy #CIA::TODMIN
+ sta (cia),y
+ lda TM + tm::tm_sec
+ jsr dec2BCD
+ ldy #CIA::TODSEC
+ sta (cia),y
+
+ jsr ldax0sp
+ ldy #3+timespec::tv_nsec
+ jsr ldeaxidx
+ jsr pusheax
+ jsr load_tenth
+ jsr tosdiveax
+ ldy #CIA::TOD10
+ sta (cia),y
+
+ jsr incsp3
+
+ lda #0
+ tax
+ jmp restore_bank
+
+.endproc
+
+;----------------------------------------------------------------------------
+; Just sum up the value in BCD mode.
+; http://forum.6502.org/viewtopic.php?p=7629#p7629
+
+.proc dec2BCD
+
+ tax
+ dex
+ bmi @L9
+ lda #0
+ clc
+ sed
+@L1: adc #1
+ dex
+ bpl @L1
+ cld
+@L9: rts
+
+.endproc
--- /dev/null
+;
+; Oliver Schmidt, 16.8.2018
+;
+; Common stuff for the clock routines
+;
+
+ .include "cbm610.inc"
+
+ .export TM, load_tenth
+
+ .importzp sreg
+
+
+;----------------------------------------------------------------------------
+.code
+
+.proc load_tenth
+
+ lda #<(100 * 1000 * 1000 / $10000)
+ ldx #>(100 * 1000 * 1000 / $10000)
+ sta sreg
+ stx sreg+1
+ lda #<(100 * 1000 * 1000)
+ ldx #>(100 * 1000 * 1000)
+ rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; TM struct with date set to 1970-01-01
+.data
+
+TM: .word 0 ; tm_sec
+ .word 0 ; tm_min
+ .word 0 ; tm_hour
+ .word 1 ; tm_mday
+ .word 0 ; tm_mon
+ .word 70 ; tm_year
+ .word 0 ; tm_wday
+ .word 0 ; tm_yday
+ .word 0 ; tm_isdst