*************************************************************************
* Nome: Serial.S							*
*									*
* Autore: Fabrizio Farenga						*
*									*
* Commento: La routine invia due diverse stringhe verso la porta	*
*	    seriale by-passando completamente il serial.device.		*
*									*
* Versione: 1.2								*
*									*
* Ultimo aggiornamento: 29-Dic-93					*
*									*
* Bugs: Nessuno conosciuto						*
*									*
*************************************************************************

;Registri dei chip custom utilizzati

dmaconr     EQU   $DFF002
vhposr	    EQU   $DFF006
serdatr     EQU   $DFF018
intenar     EQU   $DFF01C
intreqr     EQU   $DFF01E
serdat	    EQU   $DFF030
serper	    EQU   $DFF032
dmacon	    EQU   $DFF096
intena	    EQU   $DFF09A
intreq	    EQU   $DFF09C
adkcon	    EQU   $DFF09E
color	    EQU   $DFF180

;Registri dei CIA utilizzati

CIAAPRA	    EQU   $BFE001
CIABPRA     EQU   $BFD000
CIABDDRA    EQU   $BFD200


;Funzioni dell'Exec.library utilizzati

_LVODisable:	EQU -120
_LVOEnable:	EQU -120
_LVOSuperState:	EQU -150
_LVOUserState:	EQU -156


AFB_68010:	EQU 0
AttnFlags:	EQU $128

;*******************************************************
BAUD	EQU 2400		;Baud Rate da utilizzare
;*******************************************************

SERBAUD	EQU (3546895/BAUD)-1	;Converti il Baud Rate in formato Paula

CALLEXEC: MACRO
	move.l 4.w,a6
	jsr	_LVO\1(a6)
	ENDM


Start:
	CALLEXEC Disable

	move.l	4.w,a6				;Abbiamo un 68010 o superiore?
	move.w	AttnFlags(a6),d0
	btst	#AFB_68010,d0
	beq	NoClearVBR

	CALLEXEC SuperState
	movec	VBR,d7				;In caso affermativo azzera il
	move.l	d7,OldVBR			;VBR preservandolo pero' in
	moveq	#0,d7				;OldVBR.
	movec	d7,VBR
	CALLEXEC UserState
NoClearVBR:

	move.w	INTENAR,OLDINTENA		;Spegne tutte le IRQ
	move.w	#$7fff,INTENA
	move.w	#$7fff,INTREQ

	move.w	#SERBAUD,SERPER			;Immetti il Baud Rate
	
	move.l	$64,OLDTBEIRQ			;Preserva le due IRQ che ci 
	move.l	$74,OLDRBFIRQ			;interessano.

	move.l	#TBEIRQ,$64			;Inizializza i puntatori alle
	move.l	#RBFIRQ,$74			;due IRQ che ci interessano.

	move.w	#%1100100000000001,INTENA	;Attiva le 2 IRQ necessarie.
	move.w	#%0000100000000000,ADKCON	;Azzera il break.

	move.b	#$ff,CIABDDRA			;Segnala il DTR.
	move.b	#$78,CIABPRA			;(Terminale pronto)

	move.l	#INIT,CurOutputBUF		;Invia verso la porta seriale
	move.w	#0,OutputPointer		;la stringa di INIT.
	jsr	OutputChar

WaitMouse:
	btst	#6,CIAAPRA			;Attendi la pressione del tasto
	bne	WaitMouse			;sinistro del Mouse.

	move.l	#RESET,CurOutputBUF		;Invia verso la porta seriale
	move.w	#0,OutputPointer		;la stringa di RESET.
	jsr	OutputChar

WaitEnd
	tst.w	OutputPointer			;Aspetta che tutti i caratteri
	bpl	WaitEnd				;siano stati inviati.

	move.b	#$F8,CIABPRA			:Azzera i bit della seriale.

	move.w	#$7fff,INTENA			;Ripristina il sistema.
	move.l	OLDTBEIRQ,$64
	move.l	OLDRBFIRQ,$74
	move.w	OLDINTENA,d0
	bset	#15,d0
	move.w	d0,INTENA

	move.l	4.w,a6
	move.w	AttnFlags(a6),d0
	btst	#AFB_68010,d0
	beq	NoSetVBR

	CALLEXEC SuperState
	move.l	OldVBR,d7
	movec	d7,VBR
	CALLEXEC UserState
NoSetVBR:

	CALLEXEC Enable
	rts

RBFIRQ:
	move.w	#%0000100000000000,INTREQ	;Conferma tutte le IRQ 5
	movem.l	d0-d7/a0-a6,-(sp)

	move.w	#$FFF,COLOR			;Fai lampeggiare di bianco lo
						;schermo.
	jsr	InputChar			;Nuovo carattere ricevuto.

	movem.l	(sp)+,d0-d7/a0-a6
	rte

TBEIRQ:
	move.w	#%0000000000000001,INTREQ	;Conferma tutte le IRQ 1
	movem.l	d0-d7/a0-a6,-(sp)

	move.w	#$F00,COLOR			;Fai lampeggiare di rosso lo
						;schermo.
	jsr	OutputChar			;Invio del nuovo carattere.

	movem.l	(sp)+,d0-d7/a0-a6
	rte

CurOutputBUF:	dc.l Nop
OutputPointer:	dc.w 0
InputBUF:	dcb.b 256,0
InputPointer:	dc.w 0

OutputChar:
	move.w	OutputPointer,d0	;Invia un nuovo carattere prendendolo
	move.l	CurOutputBUF,a0		;dal CurOutputBuf.
	move.b	(a0,d0),d0
	beq	NoMoreOutputChar
	add.w	#1,OutputPointer	;Ad ogni carattere inviato incrementa
	and.w	#$FF,d0			;l'OutputPointer.
	or.w	#$100,d0
	move.w	d0,SERDAT
	rts
NoMoreOutputChar:			;Appena incontra un $00 nella stringa
	move.w	#-1,OutputPointer	;da inviare, immette -1
	rts				;nell'OutputPointer.
	
InputChar:
	move.w	InputPointer,d0		;Immette il carattere appena ricevuto
	lea	InputBUF,a0		;nell'InputBUF.
	move.w	SERDATR,d1
	and.w	#$FF,d1
	move.b	d1,(a0,d0)
	cmp.w	#$FF,d0			;Se nell'InputBUF si depositano piu'
	beq	NoMoreInputChar		;di 255 caratteri non ne memorizzare
	add.w	#1,InputPointer		;piu'.
	rts
NoMoreInputChar:
	rts

Nop:	dc.b 0,0

;*******************************************************
INIT:	dc.b "ATA",$0D,0		;Stringa di inizializzazione.
RESET:	dc.b "ATH0",$0D,0		;Stringa di reset (in uscita).
;*******************************************************

	CNOP 0,2

OldINTENA:	dc.w 0

OLDTBEIRQ:	dc.l 0
OLDRBFIRQ:	dc.l 0
OLDVBR:		dc.l 0

VER:	dc.b "$VER: Serial 1.2 (29.12.93) By Fabrizio Farenga",0

