Added clock_settime() for some CBMs.

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!
This commit is contained in:
Oliver Schmidt 2018-08-18 01:13:02 +02:00
parent cb7ec508f6
commit eb9872c684
12 changed files with 573 additions and 130 deletions

View File

@ -7,12 +7,10 @@
.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
;----------------------------------------------------------------------------
@ -50,12 +48,7 @@
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
@ -88,37 +81,3 @@
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

83
libsrc/c128/settime.s Normal file
View File

@ -0,0 +1,83 @@
;
; 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

64
libsrc/c128/tmcommon.s Normal file
View File

@ -0,0 +1,64 @@
;
; 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

View File

@ -7,12 +7,10 @@
.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
;----------------------------------------------------------------------------
@ -50,12 +48,7 @@
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
@ -88,40 +81,3 @@
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

83
libsrc/c64/settime.s Normal file
View File

@ -0,0 +1,83 @@
;
; 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

67
libsrc/c64/tmcommon.s Normal file
View File

@ -0,0 +1,67 @@
;
; 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

View File

@ -12,6 +12,7 @@
.import pushax, pusheax, tosmul0ax, steaxspidx, incsp1
.import sys_bank, restore_bank
.import TM, load_tenth
.importzp sreg, tmp1, tmp2
@ -54,12 +55,7 @@
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
@ -96,17 +92,3 @@
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

93
libsrc/cbm510/settime.s Normal file
View File

@ -0,0 +1,93 @@
;
; 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

41
libsrc/cbm510/tmcommon.s Normal file
View File

@ -0,0 +1,41 @@
;
; 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

View File

@ -12,6 +12,7 @@
.import pushax, pusheax, tosmul0ax, steaxspidx, incsp1
.import sys_bank, restore_bank
.import TM, load_tenth
.importzp sreg, tmp1, tmp2
@ -54,12 +55,7 @@
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
@ -96,18 +92,3 @@
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

93
libsrc/cbm610/settime.s Normal file
View File

@ -0,0 +1,93 @@
;
; 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

41
libsrc/cbm610/tmcommon.s Normal file
View File

@ -0,0 +1,41 @@
;
; 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