; =============================================================================
;
;                          Litos8 parallel LPT ports
;
; =============================================================================

; -----------------------------------------------------------------------------
; Exported user functions (7):
;	LPTSet - initialize printer
;	LPTSend - send byte to LPT port
;	LPTState - get LPT port state
;	LPTPort - get address of LPT port
;	LPTCheck - check LPT port
;	LPTGetNum - get number of LPT ports
;	LPTWrite - write data to LPT port
; -----------------------------------------------------------------------------

		CODEINIT_SECTION

; -----------------------------------------------------------------------------
;                       INIT: Initialize LPT ports
; -----------------------------------------------------------------------------

; ------------- initialize printers

LPTInit:	mov	bl,LPT_MAX-1	; BL <- index of last LPT
LPTInit2:	call	LPTSet		; initialize printer
		dec	bl		; BL <- next LPT port
		jns	short LPTInit2	; initialize next LPT port
		ret


		CODE_SECTION

; -----------------------------------------------------------------------------
;                            Initialize printer
; -----------------------------------------------------------------------------
; INPUT:	BL = LPT port index (0..2)
; OUTPUT:	CY = invalid LPT port or operation error
; NOTES:	Sends 08h and 0Ch bytes to printer control port.
; -----------------------------------------------------------------------------

LPTSet:		push	ax		; push AX
		mov	ah,1		; AH <- function code
		call	LPTInt		; LPT port service
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                             Send byte to LPT port
; -----------------------------------------------------------------------------
; INPUT:	AL = byte to send
;		BL = LPT port index (0..2)
; OUTPUT:	CY = invalid LPT port or operation error (time-out, no paper)
; -----------------------------------------------------------------------------

LPTSend:	push	ax		; push AX
		mov	ah,0		; AH <- function code
		call	LPTInt		; LPT port service
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                             Get LPT port state
; -----------------------------------------------------------------------------
; INPUT:	BL = LPT port index (0..2)
; OUTPUT:	AH = printer status
;			bit 0: 1=time-out error
;			bit 3: 1=I/O error
;			bit 4: 1=printer selected
;			bit 5: 1=out of paper
;			bit 6: 1=acknowledgement from printer
;			bit 7: 1=printer not busy, 0=printer busy
;		CY = invalid COM port or operation error
; -----------------------------------------------------------------------------

LPTState:	mov	ah,2		; AH <- function code

; === LPTInt must follow

; -----------------------------------------------------------------------------
;                         Call LPT port interrupt
; -----------------------------------------------------------------------------
; INPUT:	BL = LPT port index (0..2)
; OUTPUT:	CY = invalid LPT port or operation error
;		AH = printer status
; -----------------------------------------------------------------------------

LPTInt:		call	LPTCheck	; check LPT port
		jc	short LPTInt4	; invalid LPT port

		push	dx		; push DX
		mov	dl,bl		; DL <- LPT port		
		int	17h		; call LPT port service
		pop	dx		; pop DX

		push	ax		; push AX
		and	ah,B5+B4+B3+B0	; status bits
		cmp	ah,B4		; check paper,selected,no err,no t-out
		je	short LPTInt2	; state is OK
		stc			; set error flag
LPTInt2:	pop	ax		; pop AX

LPTInt4:	ret

; -----------------------------------------------------------------------------
;                           Get address of LPT port
; -----------------------------------------------------------------------------
; INPUT:	BL = LPT port index (0..2)
; OUTPUT:	AX = addres of LPT port (378h=LPT1,278h=LPT2,3b0h=LPT3,0=none)
;		CY = invalid LPT port (AX = 0)
; -----------------------------------------------------------------------------

LPTPort:	xor	ax,ax		; AX <- 0, invalid LPT port
		call	LPTCheck	; check LPT port
		jc	short LPTPort4	; invalid LPT port
		push	bx		; push BX
		mov	bh,0		; BX <- LPT port index
		shl	bx,1		; BX <- offset in address table
		mov	ax,[408h+bx]	; AX <- LPT port address
		pop	bx		; pop BX
LPTPort4:	ret

; -----------------------------------------------------------------------------
;                              Check LPT port
; -----------------------------------------------------------------------------
; INPUT:	BL = LPT port index (0..2)
; OUTPUT:	CY = invalid LPT port
; -----------------------------------------------------------------------------

LPTCheck:	push	bx		; push BX
		cmp	bl,LPT_MAX	; check LPT index
		cmc			; CY = error
		jc	short LPTCheck4	; invalid LPT port
		mov	bh,0		; BX <- LPT port index
		shl	bx,1		; BX <- offset in address table
		cmp	word [408h+bx],1 ; check if LPT port address is valid
LPTCheck4:	pop	bx		; pop BX
		ret

; -----------------------------------------------------------------------------
;                          Get number of LPT ports
; -----------------------------------------------------------------------------
; OUTPUT:	AL = number of LPT ports
; -----------------------------------------------------------------------------

LPTGetNum:	mov	al,LPT_MAX	; AL <- counter of LPT ports
		push	bx		; push BX
		mov	bl,LPT_MAX-1	; BL <- index of last LPT
LPTGetNum2:	call	LPTCheck	; check LPT port
		sbb	al,0		; decrease number of LPT ports
		dec	bl		; BL <- next LPT port
		jns	short LPTGetNum2 ; check next LPT port
		pop	bx		; pop BX
		ret

; -----------------------------------------------------------------------------
;                           Write data to LPT port
; -----------------------------------------------------------------------------
; INPUT:	BL = LPT port index (0..2)
;		CX = number of bytes
;		DI = source buffer
; OUTPUT:	CY = invalid LPT port or operation error (CX > 0)
;		CX = remaining bytes (or CX = 0 if no error NC)
; -----------------------------------------------------------------------------

; ------------- push registers

LPTWrite:	push	ax		; push AX
		push	si		; push SI

; ------------- check zero length

		clc			; clear error flag
		jcxz	LPTWrite6	; no data

; ------------- write data
	
		mov	si,di		; SI <- source buffer
LPTWrite2:	lodsb			; AL <- load byte from buffer
		call	LPTSend		; send byte to LPT port
		jc	short LPTWrite6	; error
		loop	LPTWrite2	; send next byte

; ------------- pop registers

LPTWrite6:	pop	si		; pop SI
		pop	ax		; pop AX
		ret
