.title 'Set the time and date on the DSC-3 and DSC-4'
	.sbttl 'SETTIME'
version	==	1
revision==	0
	.pabs
	.phex
	.loc	100h
	lxi	sp,stack
;---------
;Get the date and time from the user, and store results:
; quantity- Tics Seconds Minutes Hours Months Days Year
; location- 40h  41h     42h     43h   44h    45h  46h
;
;Note: Tics and secs are set to 0 when time is entered.
;                                     D. Stein 09/05/80
;----------
;Get the current date (CD) from the in MM/DD/YY format.
;Store the values at 44h,45h, and 46h.
WBOOT	=	0
BDOS	=	5
month	=	44h
day	=	45h
year	=	46h
CDmonth:.byte	00
CDday:	.byte	00
CDyear:	.byte	00
;
read	=	0Ah
buffer	=	5Ch	;loc for keyboard buffer
bufadr:	.word	00h	;loc for current buffer chr
;
count:	.byte	00	;chr counter for'prterr'arrow
flag:	.byte	00	;for jump-backs from 'prterr'
;set the length of the console buffer (at 5Ch).
	lxi	H,buffer;1st addr of buffer
	mvi	A,10
	mov	M,A	;10 chr buffer
;
getdate:
;print instruction line
	lxi	H,datmsg
	call	prtmsg
;set the flag for date function and initialize counter
	mvi	A,0	;flag value for date function
	sta	flag
	mvi	A,23	;no. of chrs in datmsg
	sta	count
;read the console buffer
	mvi	C,read	;bdos function
	lxi	D,buffer;address of buffer
	call	BDOS	;BDOS entry point
;set buffer addr and pass first two chrs
	lxi	H,buffer
	inx	H
	inx	H
	shld	bufadr	;addr of buffer
;get the month (MM) entry from buffer
	call	getchr	;month returns in A
	cpi	13
	jp	prterr
	cpi	1
	jm	prterr
	sta	CDmonth
;eat the delimeter chr
	call	eatchr
;get the day (DD) from user
	call	getchr	;day returns in A
	cpi	32
	jp	prterr
	cpi	1
	jm	prterr
	sta	CDday
;eat the delimter chr
	call	eatchr	
;get year (YY) from user
	call	getchr	;year returns in A
	cpi	100	
	jp	prterr
	cpi	1
	jm	prterr
	sta	CDyear
;---------
; Valid date successfully received from user.
; Store CD values at 44h,45h,46h.
;
	lda	CDmonth
	lxi	D,month
	stax	D
	lda	CDday
	lxi	D,day
	stax	D
	lda	CDyear
	lxi	D,year
	stax	D
;----------
;Now we clear the buffer
	lxi	B,6	; length of buffer
	lxi	D,buffer; address of buffer
	lxi	H,clrbuf; zeros for buffer
	ldir
;----------
; Get the real time (RT) from user in hours and min-
; utes. Store the values (minutes & hours) at 42h 
; and 42h.  Zero the seconds when data is entered.
tics	=	40h	; 60th's of a second
seconds	=	41h
minutes	=	42h
hours	=	43h
RTmins:	.byte	00
RThrs:	.byte	00
;
;----------
gettime:
;set the flag for time function and set the counter
	mvi	A,1
	sta	flag	;for 'prterr' jump-backs
	mvi	A,20	;chrs in timmsg
	sta	count	;chr counter
;set the length of the console buffer (at 5Ch)
	lxi	H,buffer;1st addr of buffer
	mvi	A,6	;6 chr buffer
	mov	M,A
;print instruction line
	lxi	H,timmsg
	call	prtmsg
;read the console buffer
	mvi	C,read	;bdos function
	lxi	D,buffer
	call	BDOS	; BDOS entry point
;set buffer addr and pass first two chrs (5Ch and 5Dh)
	lxi	H,buffer
	inx	H
	inx	H
	shld	bufadr
;get hours (two chrs) from buffer
	call	getchr	;hour returns in A
	cpi	24	;more than 23 oclock?
	jp	prterr	;bad entry, too high
	cpi	0
	jm	prterr	;bad entry, too low
	sta	RThrs	;save hours
;eat delimiter
	call	eatchr
;get minutes (two chrs) from buffer
	call	getchr	;hour returns in A
	cpi	60	;more than 59 mins?
	jp	prterr	;bad entry, too high
	cpi	0
	jm	prterr	;bad entry, too low
	sta	RTmins	;save minutes
;----------
;Time entry is OK. Store hours,minutes.
;Zero tics and seconds.
	lda	RThrs	;real time hours
	lxi	D,hours
	stax	D	;store at 43h
	lda	RTmins	;real time minutes
	lxi	D,minutes
	stax	D	;store at 42h
	mvi	A,0
	lxi	D,seconds
	stax	D	;0 seconds 
	lxi	D,tics
	stax	D	;0 tics
	
;Finished. Space down and warm boot.
	lxi	H,crlf
	call	prtmsg
	jmp	WBOOT
;----------
;		Subroutine: getchr
; Read two characters from console buffer,
; turn them into a numeric byte, increment
; chr counter and return.
; Regs in:	none
; Regs out:	A = byte
; Destroyed:	B,C,H,L
getchr:
;get 1st chr and increment bufadr,count
	lhld	bufadr	
	mov	A,M	;1st chr in A
	inx	H
	shld	bufadr	;move bufadr to next chr
	lxi	H,count
	inr	M	;increment chr counter 
	cpi	0Dh	;carriage ret?
	jz	prterr
	sbi	'0'	;ascii to numeric
;multiply first chr by 10 and save
	mov	B,A
	rlc
	rlc
	rlc
	mov	C,A
	mov	A,B
	rlc
	add	C
	push	PSW	;save 1st chr
;Get 2nd chr. Increment bufadr,count
	lhld	bufadr
	mov	A,M	;2nd chr in A
	inx	H
	shld	bufadr	;move bufadr to next chr
	lxi	H,count
	inr	M	;increment chr counter
	cpi	0Dh	;carriage return
	jz	prterr
	sbi	'0'	;ascii to numeric
;Combine the two bytes and return
	pop	B	;get first chr
	add	B
	ret
;----------
;		Subroutine:	eatchr
; Regs  in:	none
; Regs out:	none
; Destroyed:	A,H,L
;Advance buffer past an expected delimiter and
;increment the chr counter. Numeric delimeters
;are not accepted.
eatchr:
	lxi	H,count
	inr	M	;incr chr counter
	lhld	bufadr	;get buffer chr addr
	mov	A,M	;get delimiter
	cpi	0Dh	;carriage return?
	jz	prterr
	sbi	'0'
	cpi	0
	jm	aa1	;entry is ok
	cpi	10
	jp	aa1	;entry is ok
	jmp	prterr	;entry is numeric.
aa1:	inx	H
	shld	bufadr	;mov to next buffer addr
	ret
;----------
;		Subroutine: cvtbcd
; Regs  in:	A=byte to be converted
; Regs out:	A=byte, in BCD format
; Destroyed:	B
;Convert binary to BCD
cvtbcd:
	ora	A
	rz
	mov	B,A
	xra	A
..1:	inr	A
	daa
	djnz	..1
	ret
;----------
;		Subroutine: CONIN
;Fetch a character from the console.
;Subtract 30h from the inputted value,
; and abort if it is a ^C.
CONIN:	mvi	C,1
	call	05	;BDOS
	cpi	3	;3 is ^C
	jz	WBOOT	;boot if ^C
	sbi	'0'	;ascii to d
	ret
;----------
;		Subroutine: prtmsg
; Print a message on the console
;  Regs in:	HL = address of string (ended by null)
;  Regs out:	none
;  Destroyed:	A, HL
prtmsg:
	mov	A,M
	ora	A
	rz
	call	CONOUT
	inx	H
	jmpr	prtmsg
;----------
;		Subroutine: prterr
; Print an arrow underneath the error and
; print the error message on the console.
;  Regs in:	none
;  Regs out:	none
;  Destroyed:	A, HL
prterr:
;space down a line
	lxi	H,crlf
	call	prtmsg
;space over to error and print an arrow
	lda	count	;no. of chrs on the console line
prtspa:	push	PSW
	mvi	A,' '
	call	CONOUT
	pop	PSW
	dcr	A
	cpi	0	;are we underneath the error?
	jnz	prtspa	;no, back to prtspa
	mvi	A,'^'
	call	CONOUT	;print the arrow under error
	lxi	H,errmsg
	call	prtmsg
	lxi	H,crlf
	call	prtmsg
;examine 'flag' for return point.
	lda	flag
	cpi	0
	jz	getdate	;error occured during date fct.
	jmp	gettime	;error occured during time fct.
;
;----------
;		Subroutine: CONOUT
; Print a character on the console
;  Regs in:	A = character to be printed
;  Regs out:	none
;  Destroyed:	C
CONOUT:
	mov	C,A
	lxi	D,09h
	lixd	WBOOT+1
	dadx	D
	pcix
;----------
; Messages
setmsg:	.ascii	[0Dh][0Ah]'SETTIME VER '
	.byte	version+'0','.'
	.byte	revision/10+'0',revision@10+'0'
	.asciz	[0Dh][0Ah]
datmsg: .asciz	[0Dh][0Ah]' Enter Date  MM/DD/YY - '
timmsg:	.asciz	[0Dh][0Ah]' Enter Time  HH:MM - '
errmsg:	.ascii	[0Dh][0Ah]' Incorrect entry. '
	.ascii  'Control-C aborts program.  '
	.asciz	'Please try again.'
crlf:	.asciz	[0Dh][0Ah]
clrbuf:	.ascii	'XXXXXXX'
	.blkb	30
stack:
	.end
