From 8799352a3113ac34d880013246cc351533e18c76 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 2 Dec 2019 18:44:11 -0800 Subject: [PATCH] CP/M 3 RTC Support CP/M 3 will now get current date/time from RTC. Setting RTC from CP/M 3 is not finished. --- Source/CPM3/boot.z80 | 189 +++++++++++++++++++++++++++++++++++++++-- Source/CPM3/zpmldr.com | Bin 4608 -> 0 bytes Source/HBIOS/dsrtc.asm | 14 +-- 3 files changed, 190 insertions(+), 13 deletions(-) delete mode 100644 Source/CPM3/zpmldr.com diff --git a/Source/CPM3/boot.z80 b/Source/CPM3/boot.z80 index a870edea..845325f1 100644 --- a/Source/CPM3/boot.z80 +++ b/Source/CPM3/boot.z80 @@ -11,6 +11,7 @@ extrn @sysdr,@ccpdr extrn dph0 extrn @dtbl,@ctbl + extrn @date,@hour,@min,@sec include ver.inc @@ -359,11 +360,179 @@ rl$1: endif - ; No external clock. ?time: + + ; branch to get or set routine + ld a,c ; get switch value + or a ; test for zero + jr nz,time$set ; 0 means get time, else set time + + ; RTC -> cpm date/time in SCB + + ; read time from RTC + ld b,020h ; HBIOS func: get time + ld hl,tim$buf ; time buffer + rst 08 ; do it + + ; convert yymmss in time buffer -> cpm3 epoch date offset + call date2cpm ; time buf (yr, mon, day) -> SCB (@date) + + ; set time fields in SCB + ld a,(tim$hr) ; get hour from time buf + ld (@hour),a ; ... and put in SCB + ld a,(tim$min) ; get minute from time buf + ld (@min),a ; ... and put in SCB + ld a,(tim$sec) ; get second from time buf + ld (@sec),a ; ... and put in SCB + + ret + +time$set: + ; CPM date/time in SCB -> RTC + + ; convert CPM3 epoch date offset in SCB -> yymmss in time buffer + call cpm2date ; SCB (@date) -> time buf (yr, mon, day) + + ; copy CPM3 time values from SCB -> time buffer + ld a,(@hour) ; get hour from SCB + ld (tim$hr),a ; ... and put in tim$hr + ld a,(@min) ; get minute from SCB + ld (tim$min),a ; ... and put in tim$min + ld a,(@sec) ; get second from SCB + ld (tim$sec),a ; ... and put in tim$sec + + ; send time to RTC + ld b,021h ; HBIOS func: set time + ld hl,tim$buf ; ... from time buffer + rst 08 ; do it + + ret + +date2cpm: + ; Convert YYMMSS from time buffer at HL + ; into offset from CPM epoch and store + ; result in SCB. + + ld hl,0 ; initialize day counter + ; Add in days for elapsed years + ld a,(tim$yr) ; get current year + call bcd2bin ; convert to binary + sub 78 ; epoch year + jr nc,d2c1 ; if not negative, good to go + add a,100 ; else, adjust for Y2K wrap +d2c1: + ld b,a ; loop counter + ld c,3 ; leap counter, 78->79->80, so 3 + ld de,365 ; days in non-leap year + or a ; check for zero + jr z,d2c10 ; skip if zero +d2c2: + add hl,de ; add non-leap days + dec c ; dec leap counter + jr nz,d2c3 ; if not leap, bypss leap inc + inc hl ; add leap day + ld c,4 ; reset leap year counter +d2c3: + djnz d2c2 ; loop for all years +d2c10: + ; Add in days for elapsed months + ex de,hl ; save HL in DE + ld hl,daystbl ; point to table of cum days by month + ld a,(tim$mon) ; get current month + call bcd2bin ; convert to binary + dec a ; index from zero + rlca ; table entries are 2 bytes + call addhla ; offset to desired month entry + ld a,(hl) ; get the entry into HL + inc hl ; ... + ld h,(hl) ; ... + ld l,a ; ... + ex de,hl ; HL = day count, DE = months count + add hl,de ; add months count into day count + ; Add leap day for current year if appropriate + dec c ; C still has leap counter + jr nz,d2c20 ; skip if not leap year + ld a,(tim$mon) ; get cur mon + cp 3 ; March? + jr c,d2c20 ; skip if mon less than March + inc hl ; add leap day for cur year +d2c20: + ; Add in days elapsed within month + ; Note that we don't adjust the date to be a zero + ; offset which seems wrong. From what I can tell + ; the CP/M epoch is really 1/0/1978 rather than the + ; 1/1/1978 that the documentation claims. Below seems + ; to work correctly. + ld a,(tim$day) ; get day + call bcd2bin ; make binary + call addhla ; add in days + ld (@date),hl ; store in SCB ret - ; CP/M BDOS Function Interfaces +cpm2date: + ; Convert CPM epoch date offset in SCB + ; into YYMMSS values and store result in + ; time buffer at HL. + ld a,019h + ld (tim$yr),a + ld a,001h + ld (tim$mon),a + ld a,001h + ld (tim$day),a + + ret + +daystbl: + ; cumulative days elapsed by month (non-leap year) + dw 0 ; January + dw 31 ; February (non-leap) + dw 59 ; March + dw 90 ; April + dw 120 ; May + dw 151 ; June + dw 181 ; July + dw 212 ; August + dw 243 ; September + dw 273 ; October + dw 304 ; November + dw 334 ; December + +bcd2bin: + ; convert A from packed bcd to binary + push bc + ld c,a + and 0F0h + srl a + ld b,a + srl a + srl a + add a,b + ld b,a + ld a,c + and 0Fh + add a,b + pop bc + ret + +bin2bcd: + ; convert A from binary to packed bcd + push bc + ld b,10 + ld c,-1 +bin2bcd1: + inc c + sub b + jr nc,bin2bcd1 + add a,b + ld b,a + ld a,c + add a,a + add a,a + add a,a + add a,a + or b + pop bc + ret open: ld c,15 @@ -401,11 +570,20 @@ fcb$nr db 0,0,0 @bootdu db 0 hdspv db 2 ; slices per volume for hard disks (must be >= 1) + ; RTC time buffer (all values packed bcd) +tim$buf: +tim$yr db 0 +tim$mon db 0 +tim$day db 0 +tim$hr db 0 +tim$min db 0 +tim$sec db 0 + ; RomWBW CBIOS page zero stamp starts at $40 ; $40-$41: Marker ('W', ~'W') ; $42-$43: Version bytes: major/minor, update/patch ; $44-$45: CBIOS Extension Info address -; + stploc equ 40h stpimg db 'W',~'W' ; marker db rmj << 4 | rmn ; first byte of version info @@ -413,15 +591,14 @@ stpimg db 'W',~'W' ; marker dw cbx ; address of cbios ext data stpsiz equ $ - stpimg -; ; The following section contains key information and addresses for the ; RomWBW CBIOS. A pointer to the start of this section is stored with ; with the CBX data in page zero at $44 (see above). -; + cbx: devmapadr dw 0 ; device map address drvtbladr dw @dtbl ; drive map address (filled in later) dphtbladr dw dph0 ; dpb map address cbxsiz equ $ - cbx -; + end diff --git a/Source/CPM3/zpmldr.com b/Source/CPM3/zpmldr.com deleted file mode 100644 index d355f5747753d524e8a110dae1d04b963734892f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4608 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 diff --git a/Source/HBIOS/dsrtc.asm b/Source/HBIOS/dsrtc.asm index 64d52464..34a6a4e8 100644 --- a/Source/HBIOS/dsrtc.asm +++ b/Source/HBIOS/dsrtc.asm @@ -639,13 +639,13 @@ DSRTC_TEMP .DB 0 ; TEMP VALUE STORAGE ; FIELDS BELOW MATCH ORDER OF DS-1302 FIELDS (BCD) ; DSRTC_BUF: -DSRTC_SEC: .DB 0 ; SECOND -DSRTC_MIN: .DB 0 ; MINUTE -DSRTC_HR: .DB 0 ; HOUR -DSRTC_DT: .DB 0 ; DATE -DSRTC_MON: .DB 0 ; MONTH -DSRTC_DAY: .DB 0 ; DAY OF WEEK -DSRTC_YR: .DB 0 ; YEAR +DSRTC_SEC .DB 0 ; SECOND +DSRTC_MIN .DB 0 ; MINUTE +DSRTC_HR .DB 0 ; HOUR +DSRTC_DT .DB 0 ; DATE +DSRTC_MON .DB 0 ; MONTH +DSRTC_DAY .DB 0 ; DAY OF WEEK +DSRTC_YR .DB 0 ; YEAR ; ; DSRTC_TIMBUF IS TEMP BUF USED TO STORE TIME TEMPORARILY TO DISPLAY ; IT.