title 'SmartWatch utility for XBIOS system ' ; Program: SWX ; Author: Malcom Kemp ; Date: September 2, 1987 ; Version: 0.8 ; NOTE: ; This routine is copyright (C) 1987 by Xsystems Software, 4708 Elam Forest Drive, ; Stone Mountain, GA 30083, all rights reserved. Users are hereby granted a limited ; license to copy this program for personal use only. The program may be distributed ; unmodified to all interested parties. No fee or other consideration shall be ; accepted by any party or parties. ; My thanks to Robert Paddock for permission to use the routines from his program ; "SWTIME", which eased the development of this program. Any parties interested ; in the operation of the Dallas Semiconductor SmartWatch should refer to the comments ; in that program. ; vers equ 0 ; Release version verp equ ' ' z3env equ 0fe00h fcb equ 5Ch ; Default file control block cr equ 13 lf equ 10 ctrl_c equ 3 no equ 0 yes equ not no test equ no wboot equ 0 ; Warm boot entry llsec equ 128 ; Length of logical sector watch equ 0000h ; Base address of the SmartWatch. swwrb0 equ watch ; Address to write a zero bit. swwrb1 equ watch+1 ; Address to write a one bit. swrdd0 equ watch+4 ; Address to read a bit from. rstpin equ 00010000b ; We want to ignore the reset pin. oscoff equ 00100000b ; Bit 5 is high if not set. oscon equ not oscoff and 0ffh ; Bit 5 is low if set. oscrst equ oscoff or rstpin ; OSC off, ignore the reset pin. runadr equ 4000h ; Address for banked code extrn pa2hc,phl4hc,print,pstr,cout maclib ports maclib xsys jr start ; Over Copyright notice banner: call print db cr,lf,lf,'SWX--XBIOS SmartWatch Utility ' db 'Copyright (C) 1987 by Xsystems Software vers ' if mvers gt 9 db mvers/10+'0' endif db mvers mod 10 + '0','.',vers/10+'0',vers mod 10 + '0',0 ret start: ; ; Move code into place ; ld hl,fstadr ; Relocate the program ld de,runadr ; To our upper memory ld bc,lstadr-fstadr ldir ; ; Print banner ; call banner ; Check XBIOS ld hl,(wboot+1) ld l,b_time ld c,0 ; Get do nothing call call callhl ld a,h or a,l jp nz,notxbios ; We cannot run on this system ; ld hl,(wboot+1) ; ld l,b_config ; ld c,0 ; call callhl ; Get version ; ld a, ; cp a, ; jp nz,wrongver ; Set up FX flag ld hl,(wboot+1) ld l,b_config ; Get configuration entry ld c,1 ; Need system config ld de,buffer ; Point to buffer call callhl ; Get data ld a,(buffer+iot_syscfg1) ; Get system config 1 byte and a,iot_fx ; Get the fx bit ld (fx),a ; And save ; Check command line ld a,(fcb+1) cp a,'/' jp z,help and a,5Fh ; Make upper case cp a,'S' jp z,set cp a,'R' jp z,read cp a,'O' jp z,off jp help ; Anything else, do help set: call readclk ; Read the watch jp z,nowatch ld c,1 ; Read system clock ld de,buffer ld hl,(wboot+1) ld l,b_time call callhl ; Get time and date ld (clkstat),a ; Save status or a,a ; Check Status jr z,set1 call print db cr,lf,'System clock not set, terminating.',0 jp wboot set1: ld a,(buffer+tmb_cy) ld (year),a ld a,(buffer+tmb_cm) ld (mon),a ld a,(buffer+tmb_cd) ld (date),a ld a,(buffer+tmb_ch) ld (hrs),a ld a,(buffer+tmb_cmn) ld (min),a ld a,(buffer+tmb_cs) ld (sec),a ld c,0 ; Clear for accumulation ld a,(buffer+tmb_cts) cp a,0FFh jr z,set_fract sla a sla a sla a sla a ld c,a ; Put in collector ld (buffer+tmb_chs),a cp a,0FFh jr z,set_fract or a,c ld c,a set_fract: ld a,c ld (fract),a ld a,(buffer+tmb_dow) inc a ; Bump up or a,rstpin ; Ignore reset ld (days),a call writeclk call print db cr,lf,lf,'SmartWatch set to system time.',0 call disptime jp wboot read: call readclk ; Read the watch jp c,notset jp z,nowatch ld a,(year) ld (buffer+tmb_cy),a ld a,(mon) ld (buffer+tmb_cm),a ld a,(date) ld (buffer+tmb_cd),a ld a,(hrs) bit 7,a ; Test for AM/PM mode jr z,no_adj res 7,a ; Get rid of bit bit 5,a ; Test PM jr z,no_adj res 5,a ; Get rid of bit ld c,12h ; Adjustment add a,c daa ; Adjust no_adj: ld (buffer+tmb_ch),a ld a,(min) ld (buffer+tmb_cmn),a ld a,(sec) ld (buffer+tmb_cs),a ld a,(fract) srl a srl a srl a srl a ld (buffer+tmb_cts),a ld a,(fract) and a,0Fh ld (buffer+tmb_chs),a ld a,(days) and a,07h dec a ld (buffer+tmb_dow),a ld c,2 ; Set system clock ld de,buffer ld hl,(wboot+1) ld l,b_time call callhl ; Put it away ld (clkstat),a ; Show clock set call print db cr,lf,lf,'System time set by SmartWatch.',0 call disptime jp wboot off: call readclk ; Read the watch jp z,nowatch ld a,(days) or a,oscrst ; Set oscillator bit ld (days),a call writeclk call print db cr,lf,lf,'SmartWatch turned off.',0 jp wboot nowatch: call print db cr,lf,'No SmartWatch present.',0 jp wboot notset: call print db cr,lf,'SmartWatch not set.',0 jp wboot if test prbuf: ld b,8 ld hl,swbuf call print db cr,lf,'Buffer: ',0 prbuf1: call print db ' ',0 ld a,(hl) call pa2hc inc hl djnz prbuf1 ret endif ; ; Display real time clock ; disptime: call print db cr,lf,0 ; Day of week ld a,(buffer+tmb_dow) ; Get day of week sla a ; *2 ld e,a ld d,0 ; Offset to DE ld hl,dowtab ; Get table add hl,de ; Address of pointer ld a,(hl) inc hl ld h,(hl) ld l,a ; Get string pointer in HL call pstr ; Print day id call print db 'day, ',0 ; Month ld a,(buffer+tmb_cm) ; Get month call bcd_to_bin ; In binary dec a ; Take care of starting at month 1 sla a ; *2 ld e,a ld d,0 ; Offset to DE ld hl,monthtab ; Get table add hl,de ; Address of pointer ld a,(hl) inc hl ld h,(hl) ld l,a ; Get string pointer in HL call pstr ; Print month call print db ' ',0 ; Day ld a,(buffer+tmb_cd) ; Get day call pbcd_sup ; Print it with suppressed zero call print db', 19',0 ; Year ld a,(buffer+tmb_cy) ; Get year call pbcd ; Print it call print db ' ',0 ; Hour ld a,(buffer+tmb_ch) ; Get hour or a,a ; Set flags jr nz,dsptm1 ; Continue ld a,12h ; Zero, set it to 12 jr dsptm2 ; And continue dsptm1: cp a,13h ; See if after noon jr c,dsptm2 ; No, use it sub a,12h ; Set to 12hr time daa ; Adjust bits dsptm2: call pbcd ; Print it call print db ':',0 ; Minute ld a,(buffer+tmb_cmn) ; Get minute call pbcd ; Print it call print db ':',0 ; Second ld a,(buffer+tmb_cs) ; Get second call pbcd ; Print it db ' ',0 ; AM/PM ld a,(buffer+tmb_ch) ; Get hour sub a,12h jr nc,dsptm6 call print db ' AM',0 jr dsptm7 dsptm6: call print db ' PM',0 dsptm7: ld a,(clkstat) ; Get status or a,a ; Set flags ret z ; All done call print db ' (not initialized)',0 ret ; ; BCD to Binary routine ; bcd_to_bin: ld b,a ; Save and a,0F0h ; Get upper nibble ld c,a ; Save ld a,b ; Recover value ret z ; No upper, bin = bcd and a,0Fh ; Get lower nibble srl c ; *8 add a,c ; Add 8* upper nibble srl c ; *4 srl c ; *2 add a,c ; Add 2 upper nibble for total of 10 ret ; ; Print bcd value ; pbcd: ld b,a ; Save srl a srl a srl a srl a ; Get in lower nibble add a,'0' ; Make digit call cout ; Print it ld a,b ; Get value and a,0Fh ; Get lower nibble add a,'0' ; Make it a digit call cout ; Print it ret ; ; Print bcd value with suppressed leading zero ; pbcd_sup: ld b,a ; Save and a,0F0h ; Get upper nibble jr z,pbcd_sup1 ; Print lower srl a srl a srl a srl a ; Get in lower nibble add a,'0' ; Make digit call cout ; Print it pbcd_sup1: ld a,b ; Get value and a,0Fh ; Get lower nibble add a,'0' ; Make it a digit call cout ; Print it ret dowtab: dw sun dw mond dw tue dw wed dw thu dw fri dw sat sun: db 'Sun',0 mond: db 'Mon',0 tue: db 'Tues',0 wed: db 'Wednes',0 thu: db 'Thurs',0 fri: db 'Fri',0 sat: db 'Satur',0 monthtab: dw jan dw feb dw mar dw apr dw may dw jun dw jul dw aug dw sep dw oct dw nov dw dec jan: db 'January',0 feb: db 'February',0 mar: db 'March',0 apr: db 'April',0 may: db 'May',0 jun: db 'June',0 jul: db 'July',0 aug: db 'August',0 sep: db 'September',0 oct: db 'October',0 nov: db 'November',0 dec: db 'December',0 clkstat db 0 ; Status of system clock ; Startup error messages notxbios: call print db cr,lf,'SWX: Error, can only run on XBIOS system.',cr,lf,0 jp wboot wrongver: call print db cr,lf,'SWX: Error, wrong version for system macros.',cr,lf,0 jp wboot help: call print db cr,lf,lf,'Usage:' db cr,lf,lf,' SWX o' db cr,lf,lf,'Options:' db cr,lf,' S - Set SmartWatch by reading system time.' db cr,lf,' R - Read SmartWatch and set system time.' db cr,lf,' O - Turn off SmartWatch for storage' db 0 jp wboot ; ; ------------------------------------------------------------- ; fstadr: ; Start of section that must be relocated. ; ; This section contains the clock accessing routines. They must be ; relocated above the 4k address point to allow for the accessing ; of the ROM chip at logical address 0000h-0FFFh. These routines ; must not call library routines while bank is switched. ; .phase runadr ; ; Read clock and test for existance of smartwatch ; Return: Zero flag set means no watch ; Carry flag set if watch not set ; readclk: call access ; Access the smart watch call readsw ; Read the smart watch call restore ; Get environment back if test call print db cr,lf,'Read clock: ',0 call prbuf endif ; Test for smartclock present and set ld a,(days) ; A valid day will contain a 1 and a 0 cp a,0FFh ; All of the bits will be the same ret z ; if there is no SmartWatch. or a,a ; Return with the 'Z'-flag set ret z ; if no SmartWatch is found. bit 5,a ; See if reset ignore scf ; For set test ret nz ; Oscillator not on or a,0FFh ; Show everything OK ret ; ; Write the smart clock ; writeclk: call access ; Access the smart watch call writesw ; Write the smart watch call restore ; Get environment back if test call print db cr,lf,'Write clock: ',0 call prbuf endif ret ; ; Access smart watch. Turn off interrupts, dram refresh, make sure we have ; ram switched in (FX), and send accessing sequence to the chip ; access: ld a,(fx) ; Test for fx or a,a jr z,nonfx call getlatch ; Read the FX latch. ld (ltchimg),bc ; Save the latch image. res 3,b ; Select EPROM [RAM/ROM*]. call setlatch ; Set the FX latch. nonfx: di ; Shut down interrupts ; Do a software refresh ld hl,0 ; Pointer to first 256 address space ld de,1*256 ; Pointer to second 256 address space ld b,l ; set count to 256 refit: ld a,(hl) ; Read 512 bytes of dram ld a,(de) inc de inc hl djnz refit in0 a,(rcr) ; Get refresh control register ld (svrcr),a ; Save value and 7Fh out0 (rcr),a ; Turn off refresh in0 a,(cbar) ; Save the current CBAR value, ld (svcbar),a ; then map the first for 4K and 0f0h ; of ROM into Common Area 0. or 01h out0 (cbar),a ld a,(swrdd0) ; Initialize the access pointer ; in the SmartWatch. ld b,2 ; Make two passes. unlock: push bc ld a,0C5h ; Begin the unlock sequence. call wrtclk ; The odds of this pattern being ld a,3Ah ; accidentally duplicated and call wrtclk ; causing inadvertent entry to ld a,0A3h ; the SmartWatch is less than call wrtclk ; 1 in 10^19. ld a,05Ch call wrtclk pop bc djnz unlock ; Repeat one more time if needed. ret ; ; Read the clock ; readsw: ld de,swbuf ; bytes of data in the ; following order: call rdclk ; Fractions of a second, ld (de),a inc de call rdclk ; Seconds, ld (de),a inc de call rdclk ; Minutes, ld (de),a inc de call rdclk ; AM/PM, Hours, ld (de),a inc de call rdclk ; OSC,RST,DAY, ld (de),a inc de call rdclk ; Date (Day of month), ld (de),a inc de call rdclk ; Month, ld (de),a inc de call rdclk ; Years. ld (de),a inc de ret ; ; Write the clock ; writesw: ld de,swbuf ; Get our buffer ld a,(de) ; Fractions of a second, call wrtclk inc de ld a,(de) ; Seconds, call wrtclk inc de ld a,(de) ; Minutes, call wrtclk inc de ld a,(de) ; AM/PM, Hours, call wrtclk inc de ld a,(de) ; OSC,RST,Days, call wrtclk inc de ld a,(de) ; Date, call wrtclk inc de ld a,(de) ; Month, call wrtclk inc de ld a,(de) ; Year. call wrtclk ret ; ; Restore environment ; restore: ld a,(svcbar) ; Back to the normal memory map. out0 (cbar),a ld a,(svrcr) ; DRAM Hardware refresh back on. out0 (rcr),a ei ld a,(fx) or a,a ; Do we have an fx ret z ; No, go on back ld bc,(ltchimg) ; Get back original latch call setlatch ; image, then write it. ret ; ; Write a byte to the clock ; wrtclk: ld b,8 ; We must deal with 8 bits at a time. ld c,a ; Put output character in C rtcwr: rrc c ; Is this bit a one or zero? jr c,wrtone; Jump if its a one. ld a,(swwrb0) ; Write a zero by reading. jr rtcwrl wrtone: ld a,(swwrb1) ; Write a one by reading. rtcwrl: djnz rtcwr ; Do all 8 bits. ret ; ; Read a byte from the clock ; rdclk: ld hl,swrdd0 xor a ; Set all bits to zero. ld b,8 ; 8 bits make one byte. rtcrd: bit 0,(hl) ; Does bit D0=0? jr z,rdbitl ; Jump if the bit is set 0,a ; Set the bit. rdbitl: rrca ; Rotate right one bit. djnz rtcrd ; Do all of the bits. ret setlatch: or a,0FFh ; Indicate write latch jr dolatch getlatch: xor a,a ; Indicate read latch dolatch: ld hl,(wboot+1) ; Get warmboot ld l,b_latchval ; And our entry callhl: jp (hl) ; And go there, return to caller ; ltchimg: ds 2 ; Image of SB180FX latch ; ; ------------------------------------------------------------- ; svcbar: ds 1 ; Save the MMU register CBAR. svrcr: ds 1 ; Save the refresh register RCR. fx ds 1 ; = 0, no FX, <> 0 there is an FX ; lstsec: ds 1 ; Place to save the 'Last Second'. ; swbuf: ; Smart watch buffer fract: ds 1 ; Fractions of a second sec: ds 1 ; Seconds min: ds 1 ; Minutes hrs: ds 1 ; Hours days: ds 1 ; Days date: ds 1 ; Date mon: ds 1 ; Month year: ds 1 ; Years ; ; ; stack pointer. buffer ds llsec ; Buffer for system communication ; ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; .dephase ; End of logical phase block. ; ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; lstadr equ $ ; Last address of code that may ; ; need transferred. ;