; D1MicAsm.asm -- convert microcomputer time to printable format
;	Last edited: 2 May 1980

.get "MAsmCommon.d"
.get "D1RegMem.d"

; MASM
.bextz MSave2,MCount
.bext Wait

; MDATA
.bext MCTimeOut

; D1ASM
.bext LoadCPReg
.bextz D1In,D1Out

; Defined here
.bextz MCXct,MCXctR
.bext ConvertMTime,MCWaitCnt

.zrel

MCXct:		.MCXct
MCXctR:		.MCXctR

.srel

ConvertMTime:	.ConvertMTime
MCWaitCnt:	24	; count of 100 microsecond waits to timeout

.nrel

mcx100000:	100000
lvLoadCPReg:	LoadCPReg
MCAtten:	Clock+BaseBAtten
MCAttenS:	Clock+BaseBAtten+Strobe
lvMCTimeOut:	MCTimeOut
lvMCWaitCnt:	MCWaitCnt
lvWait:		Wait
MAReg0:		Mir0+MAReg03
MAReg1:		Mir0+MAReg47
MASyn0:		Mir0+InSync
Mask03:		170000

; MCXct(Val) executes Val as a microcomputer command
; Return 0 on success, -1 on timeout
.MCXct:	sta 3 1 2
	jsr @GetFrame
	 10
	jsr @StArgs
	lda 0 MASyn0
	sta 0 @D1Out	; Select D1In address of MASync
	lda 0 @D1In
	movl 0 0 szc
	mkzero 0 0 skp
	lda 0 mcx100000
	sta 0 5 2	; Save complement of MASync
	lda 1 4 2
	add 1 0		; Command with MASync
	jsrii lvLoadCPReg
	 1
	lda 0 MCAtten
; Cannot use DStrobe here because baseboard requires pulse width > 1.0
; microseconds to initiate a microcomputer interrupt.
	sta 0 @D1Out
	lda 1 MCAttenS
	sta 1 @D1Out
	sta 0 @D1Out
	lda 0 MASyn0
	sta 0 @D1Out
	lda 0 @lvMCWaitCnt
	sta 0 6 2	; Timeout counter
MCXlp:	lda 1 5 2	; Completion value of MASync
	lda 3 mcx100000	; Mask of MASync bit
	lda 0 @D1In
	and 3 0
	sub 1 0 snr
	 jsr @Return	; resultis 0
	mkone 0 0
	jsrii lvWait	; Wait 100 microseconds
	 1
	dsz 6 2
	jmp MCXlp	; Loop until acknowledge
	mkminusone 0 0	; timeout resultis -1
	lda 3 @lvMCTimeOut	; Count timeouts
	isz 0 3
	jsr @Return
	jsr @Return

; MCXctR(Val) executes Val as a microcomputer command and returns MAReg
; as the result.
.MCXctR:
	sta 3 1 2
	jsr @GetFrame
	 10
	jsr @StArgs
	lda 0 4 2
	jsr .MCXct
	 1
	lda 0 MAReg0
	sta 0 @D1Out
	lda 3 @D1In
	lda 1 Mask03
	ands 1 3	; MAReg[0:3] in AC3[10:13]
	lda 0 MAReg1
	sta 0 @D1Out
	lda 0 @D1In
	and 1 0
	cycle 4		; MAReg[4:7] in AC0[14:17]
	add 3 0
	jsr @Return

; ConvertMTime(V,DVec,lvDays,lvHours,lvMinutes,lvSeconds)
; converts the microcomputer time in DVec into printable integers.
; Microcomputer time is 6 bytes in reverse order that are the uptime
; in 102.4 msec ticks
.ConvertMTime:
	sta 3 1 2
	jsr @GetFrame
	 14
	jsr @StArgs
; First unreverse the arguments
	sta 2 MSave2
	lda 3 5 2	; DVec
	lda 2 4 2	; V
	lda 0 2 3
	cycle 10
	sta 0 0 2	; High-order word
	lda 0 1 3
	cycle 10
	sta 0 1 2	; Middle word
	lda 0 0 3
	cycle 10	; 0/ low-order word
	lda 1 1 2	; 1/ middle word
	lda 3 d10
	sta 3 MCount	; Shift count
	lda 3 0 2	; 3/ high-order word
CMTlp:	movzl 0 0
	movl 1 1
	movl 3 3
	dsz MCount
	jmp CMTlp
	sta 3 0 2	; Save time in .0001 sec in vector V
	sta 1 1 2
	sta 0 2 2
	mov 2 0
	lda 2 MSave2
	lda 1 d10000
	jsr TDivide	; Convert V to seconds
	lda 1 d60
	jsr TDivide	; Convert V to minutes, return excess seconds in 1
	sta 1 @11 2	; Save seconds
	lda 1 d60
	jsr TDivide	; Convert V to hours, return excess minutes in 1
	sta 1 @10 2	; Save minutes
	lda 1 d24
	jsr TDivide	; Convert V to days, return excess hours in 1
	sta 1 @7 2	; Save hours
	mov 0 3
	lda 0 2 3	; Assume days fits in one word
	sta 0 @6 2	; Save days
	jsr @Return

d10:	10.
d10000:	10000.
d60:	60.
d24:	24.

; TDivide(V,Divisor) replaces triple-precision vector V by V/Divisor,
; returning V in 0, remainder in 1.
TDivide:
	sta 3 1 2
	mov 0 3		; V
	mov 1 2		; Divisor
	mkzero 0 0
	lda 1 0 3	; High part of dividend
	div		; 0←remainder, 1←quotient
	77400
	sta 1 0 3	; Save high quotient
	lda 1 1 3
	div
	77400
	sta 1 1 3	; Save middle quotient
	lda 1 2 3
	div
	77400
	sta 1 2 3	; Save low quotient
	mov 0 1		; Return remainder in 1
	mov 3 0		; Return V in 0
	lda 2 MSave2
	jmp @1 2

.end