;-----------------------------------------------------------------
; MXC-KC10.ASM
; clock overlay for mex and the Kenmore Computer Technologies (KCT)
; Ztime-I real-time clock.

rev     equ     12      ;V 1.2

; V1.2  30 Aug 86 - Fixed Year storage to chip          - Rea Williams
; V1.1  26 Apr 85 - Added CSET routine                  - Joe Griffith
; V1.0  24 Apr 85 - Original, TM-KCT11.ASM              - Joe Griffith

;--------------------------------------------------------------------
;     This overlay provides the current date and time to MEX+ or higher
; versions of MEX.  It is configured for the Kenmore Computer
; Technologies (KCT) Ztime-I real-time calendar/clock although it
; will probably work with any clock using the MM58167A clock chip.

no      equ     0
yes     equ     0ffh
i8080   equ     yes             ;for xlat- do not change
i8086   equ     no
cpm     equ     yes
pcdos   equ     no
cr      equ     13
lf      equ     10

mex     equ     0D00h           ;address of the service processor
ilp     equ     240             ;inline print
sblank  equ     244             ;scan input stream to next non-blank (cy=end)
evala   equ     243             ;evaluate number from input to HL
gnc     equ     241             ;get next character
decout  equ     239             ;decimal output from HL

bport   equ     0E0h            ;base port address for KCT clock
                               ;this address should be changed to
                               ;reflect wherever your MM58167A is.
centry  equ     1900            ;hard code since it is not available
                               ;from the clock chip

;--------------------------------------------------------------------

       org     100h            ;processor type flag is here

if i8080
       db      0c3h            ;show which processor we are for
endif
if i8086
       db      0E9h
endif

;-----------------------------------------------------------------
;   JMP table for clock overlay

       org     0e00h           ;start of clock overlay

       jmp     gettim          ;get time
       jmp     getdat          ;get date
       jmp     setclk          ;cset processor
       ret                     ;clock overlay init
       nop
       nop
       ret                     ;clock overlay de-init
thisyr: db      0               ;this is actually the space reserved
                               ;for the address portion of the jmp
                               ;but no de-init is needed so the year
                               ;is stored here.  Note that the system
                               ;must be cloned after the clock is set
                               ;to permanently store the year here.
hlpflg: db      0               ;likewise the help flag is stored here

;--------------------------------------------------------------------
; subroutine GETTIM returns the time as follows:
;
; B - Hours (0-23)
; C - Minutes (0-59)
; D - Seconds (0-59)
; E - Hundreths of seconds (0-99)

gettim: in      bport+2         ;get seconds
       push    psw             ;save for future reference

       call    makbin          ;make it a binary number
       mov     d,a             ;store it
       in      bport+3         ;get minutes
       call    makbin
       mov     c,a
       in      bport+4         ;get hours
       call    makbin
       mov     b,a

       in      bport+2
       mov     l,a             ;store it
       pop     psw             ;get original seconds back
       cmp     l               ;compare the two
       jnz     gettim          ;not the same so do it over else
       mvi     e,0             ;clear hundreds of seconds
       ret

;------------------------------------------------------------------------
; subroutine GETDAT returns the date as follows:
;
; BC - Year (1985-2099)
; D - Month (1=January, 2=February, etc.)
; E - Day of month (1-31)

getdat: in      bport+2         ;get seconds
       push    psw             ;save it for future reference

       in      bport+7         ;get month
       call    makbin
       mov     d,a
       in      bport+6         ;get day of month
       call    makbin
       mov     e,a

       in      bport+2         ;get seconds again
       mov     l,a             ;store temporarily
       pop     psw             ;get original seconds
       cmp     l               ;compare the two
       jnz     getdat          ;if not the same do it over
       in      bport+9         ;get year
       call    makbin
       mov     c,a             ;put in it's proper place
       mvi     b,0
       lxi     h,centry        ;load the century
       dad     b               ;add it to the stored value
       mov     c,l             ;move hl to bc
       mov     b,h
       ret

;-----------------------------------------------------------------
;  This routine takes the two BCD values in each nibble of the
; accumulator and converts it to a single binary value.

makbin: push    d               ;save the current value
       push    psw             ;save the original value
       rrc                     ;put the 10s value in the lower bits
       rrc
       rrc
       rrc
       ani     0Fh             ;mask off whatever is in the high nibble
       add     a               ;multiply this register by 10
       mov     e,a
       add     a
       add     a
       add     e
       mov     e,a             ;save in e
       pop     psw             ;get the original value
       ani     0Fh             ;allow only low bits
       add     e               ;get total to a
       pop     d               ;restore de
       ret                     ;all done

;----------------------------------------------------------------------
;   CSET processor.  This routine allows the user to set the clock from
; command level by typing CSET yy/mm/dd hh:mm:ss.

setclk: call    ilprt
       db      'KCT Clock OVR V'
       db      rev/10+'0','.'
       db      rev mod 10+'0'
       db      cr,lf,lf,0

       xra     a               ;get a zero
       sta     hlpflg          ;store it as a flag
       call    twobcd          ;get the first two numbers
       rc
       out     bport+9         ;put in the year
       call    twobcd          ;get the month
       rc
       out     bport+7         ;put in the months counter
       call    twobcd          ;get the day of the month
       rc
       out     bport+6         ;put in the day counter
       call    twobcd          ;get the hour
       rc
       out     bport+4         ;put in the hour counter
       call    twobcd          ;get the minutes
       rc
       out     bport+3         ;put in the minutes counter
       call    twobcd          ;get the seconds
       rc
       out     bport+2         ;put in the seconds counter
       ret

;------------------------------------------------------------------
;   this routine looks at the CSET parameter and returns with a BCD
; pair in the two nibbles of the accumulator.  Blanks and separators
; are skiped.  The carry flag is set when the end of the line is
; reached.

twobcd: call    getnum          ;get the 10's digit
       jc      chlp            ;no numbers there
       rrc                     ;put it in the high nibble
       rrc
       rrc
       rrc
       push    psw             ;save it
       call    getnum          ;get the 1's
       mov     b,a             ;temporary storage
       pop     psw             ;get the 10s back
       ora     b               ;merge the two
       ret

getnum: mvi     c,gnc           ;get the next character
       call    mex
       rc                      ;carry means there is no more input
       cpi     '0'
       jc      getnum          ;char is smaller than ascii zero
       cpi     ':'
       jnc     getnum          ;char is not an ascii digit
       cmc                     ;reset carry flag
       sta     hlpflg
       sbi     '0'             ;make it a binary value
       ret

chlp:   lda     hlpflg          ;get the help flag
       cpi     0               ;is it null
       stc                     ;flag the end
       rnz                     ;if not then don't print
       call    ilprt
       db      'CSET YY/MM/DD HH:MM:SS'
       db      cr,lf,lf,0
       stc                     ;flag the system
       ret

;----------------------------------------------------------------------
; inline print routine

ilprt:  mvi     c,ilp
       jmp     mex

       end