;******************************************************************************
; INT60 per Videobank VSX500
; Author Roberto Gaspari, RVM Genova / Ciakware
; 
; Rel 1.128: 22 Jan 1991 
; Rel 1.129: 28 Jan 1991 
; Rel 1.130: 06 Feb 1991 
; Rel 1.131: 11 Mar 1991 
; Rel 1.132: 25 Mar 1991 
; Rel 1.133: 17 Dec 1992 
; Rel 1.134: 05 Apr 1993 
; Rel 1.135: 06 Apr 1993 
; Rel 1.136: 14 Sep 1994  (copia per GAMMA srl, Abano) 
; Rel 1.137: 16 Oct 1998  (copia per Buster24 per adeguare il nuovo robot Buster) 
;
; (c)1991-1998 Roberto Gaspari 
; porzioni di codice rielaborate da un progetto originale di Ing. Pietro Rotoloni (Videobank 500)
;
; TASM
;
;******************************************************************************
_CODE           SEGMENT
                ASSUME  cs:_CODE,ds:_CODE,es:_CODE
                ORG     100h

start:          jmp     installa

SNSPNC          EQU     0 ; tipo sensore pinza (1=switch,0=prossimetro)
DOORBCKGRD      EQU     1 ; chiusura porta in background (1=abilitata,0=disabilitata)
BARGP           EQU     0 ; barriere gruppo pinza (1=presenti,0=assenti)
VERPNZ          EQU     1 ; verifica apertura pinza (1=abilitata,0=disabilitata)
INT8            EQU     1 ; timer (1=tramite int 8,0=tramite int 1c)

sign            DB      13,10,'VIDEOBANK VSX500    ',13,10,'$'

filler          DB      128 DUP(?)

;******************************************************************************
;
;	gestione delle porte di output mappate fra 300h e 31fh
;
; input: dx = indirizzo
;	 al = maschera
;
;******************************************************************************

port            DB      32 DUP (0)      ; copia dei valori delle porte

resetbit        PROC	NEAR		; resetta il bit
		not	al
		mov	bx,dx
		and	[port+bx-300h],al
		mov	al,[port+bx-300h]
		out	dx,al
		ret
		ENDP

setbit		PROC	NEAR		; setta il bit
		mov	bx,dx
		or	[port+bx-300h],al
		mov	al,[port+bx-300h]
		out	dx,al
		ret
		ENDP

reversebit	PROC	NEAR		; inverte il bit
		mov	bx,dx
		xor	[port+bx-300h],al
		mov	al,[port+bx-300h]
		out	dx,al
		ret
		ENDP

;******************************************************************************
;
;	gestione degli elettromagneti
;
; input: ds:si = puntatore ai parametri del magnete
;
; output: zero-flag = stato del sensore
;
;******************************************************************************
				; parametri magnete
MGN		EQU	[si]		; indirizzo magnete
MGN_BIT		EQU	[si+2]		; bit magnete
MSNS		EQU	[si+3]		; indirizzo sensore
MSNS_BIT	EQU	[si+5]		; bit sensore

WAIT_MGN	EQU	3		; tempo attesa lettura sensore

magneteoff	PROC	NEAR		; disattiva il magnete
		mov	dx,MGN
		mov	al,MGN_BIT
		call	setbit
		jmp	SHORT magnete

magneteon:	mov	dx,MGN		; attiva il magnete
		mov	al,MGN_BIT
		call	resetbit

magnete:	mov	bx,WAIT_MGN	; attende
mgn1:		xor	cx,cx
		loop	$
		dec	bx
		jnz	mgn1
		mov	dx,MSNS		; legge sensore
		in	al,dx
		test	al,MSNS_BIT
		ret
		ENDP

;******************************************************************************
;
;	gestione dei motori passo-passo
;
; input: ds:di = puntatore ai parametri fissi del motore
;
;******************************************************************************
				; segnali motore
EN              EQU	[di]		; indirizzo abilitazione
EN_BIT		EQU	[di+2]		; bit abilitazione
DIR		EQU     [di+3]		; indirizzo direzione
DIR_BIT		EQU     [di+5]		; bit direzione
CK		EQU     [di+6]		; indirizzo clock
CK_BIT		EQU	[di+8]		; bit clock
				; parametri rampa velocit…
START_VEL	EQU	[di+9]		; velocit… di partenza
STEPS_ACC	EQU	[di+11]		; passi per accelerazione
ACC		EQU	[di+13]		; accelerazione
STEPS_DECC	EQU	[di+15]		; passi per deccelerazione
DECC		EQU	[di+17]		; deccelerazione
				; parametri traiettoria
SNS		EQU	[si]		; indirizzo sensore
SNS_BIT		EQU	[si+2]          ; bit sensore
SNS_STAT	EQU	[si+3]		; stato sensore per arresto
MAX_STEPS	EQU	[si+4]		; passi massimi prima del sensore
STEPS_SNS	EQU	[si+6]		; passi dopo il sensore

WAIT_SNS	EQU	2000		; tempo attesa verifica sensore

steps		DW	?		; contatore passi
vel		DW      ?               ; velocit… attuale

motoreoff	PROC	NEAR		; disattiva il motore
		mov	dx,EN
		mov	al,EN_BIT
		call	setbit
		ret
		ENDP

motoreon	PROC	NEAR		; attiva il motore: questa non funziona quasi mai a "freddo"
		mov	dx,EN               ; al limite ci butto un loop
		mov	al,EN_BIT
		call	resetbit
		ret
		ENDP

; 	muove il motore fino al sensore nella direzione specificata
;
; input: ds:si = puntatore ai parametri della traiettoria
;
; output: carry-flag = reset se tutto ha funzionato a dovere
;	  carry-flag = set   se non Š stato raggiunto il sensore

step		PROC	NEAR		; muove il motore di un passo
		mov	dx,CK		; tick
		mov	al,CK_BIT
		call	reversebit
		mov	cx,vel		; velocit…
		loop	$
		ret
		ENDP

motore0		PROC	NEAR		; direzione 0
		mov	dx,DIR
		mov	al,DIR_BIT
		call	resetbit
		jmp	SHORT motorego

motore1:	mov	dx,DIR		; direzione 1
		mov	al,DIR_BIT
		call	setbit

motorego:	call	motoreon	; abilita il motore

		mov	ax,START_VEL	; velocit… di partenza
		mov	vel,ax

		mov	ax,STEPS_ACC	; passi per accelerazione
		mov	steps,ax
mt1:		call	step
		mov	ax,ACC		; accellera
		sub	vel,ax
		dec	steps
		jnz	mt1

mtt1:           mov     ax,MAX_STEPS    ; passi massimi prima del sensore
		mov	steps,ax
mt2:		call	step
		mov	dx,SNS		; controlla sensore
		in	al,dx
		and	al,SNS_BIT
		xor	al,SNS_STAT
		jnz	mt3		; sensore non raggiunto
		mov	cx,WAIT_SNS	; attende stabilit… segnale
		loop	$
		in	al,dx           ; verifica sensore
		and	al,SNS_BIT
		xor	al,SNS_STAT
		jz	mt4		; sensore raggiunto
mt3:	        dec	steps
		jnz	mt2		; continua
		stc			; TROPPI PASSI !!!
		ret

mt4:		mov	ax,STEPS_SNS	; passi dopo il sensore
		mov	steps,ax
mt5:		call	step
		dec	steps
		jnz	mt5

                mov     dx,SNS          ; verifica stato fine-corsa
		in	al,dx
		and	al,SNS_BIT
		xor	al,SNS_STAT
                jnz     mtt1            ; sensore non raggiunto

		mov	ax,STEPS_DECC	; passi per deccelerazione
		mov	steps,ax
mt6:		call	step
		mov	ax,DECC		; deccellera
		add	vel,ax
		dec	steps
		jnz	mt6

		clc			; tutto ok
		ret
		ENDP

;******************************************************************************
;
;	gestione del tappeto del posto operatore
;
;******************************************************************************

ESC_KEY		EQU	011bh
F9_KEY          EQU	4300h

TEN		EQU	0310h  		; segnali motore
TEN_BIT		EQU	00001000b
TDIR		EQU	031ch
TDIR_BIT        EQU     10000000b       ; 0 -> verso l'esterno
TCK		EQU	0312h
TCK_BIT		EQU	00100000b
SNS_EST		EQU	0318h		; sensore esterno
SNS_EST_BIT     EQU     00000001b
SNS_CNT         EQU     0318h           ; sensore centrale
SNS_CNT_BIT     EQU     00000010b
SNS_INT		EQU	0318h		; sensore interno
SNS_INT_BIT     EQU     00000100b
MGN_TAPP        EQU     0318h           ; magnete blocco cassetta e micro relativo
MGN_TAPP_BIT    EQU     00000100b
MSNS_TAPP       EQU     0318h
MSNS_TAPP_BIT   EQU     10000000b
PBOX            EQU     0318h           ; sensore presenza box
PBOX_BIT        EQU     00001000b
PBOK            EQU     0310h           ; sensore presenza box ok
PBOK_BIT        EQU     00000010b

MAX_STEPS_CNT0  EQU     10000           ; passi massimi prima del sensore cnt.
MAX_STEPS_CNT1  EQU     7000            ; passi massimi durante il sensore cnt.
MAX_STEPS_EST   EQU     10000           ; passi massimi espulsione cassetta
STEPS_EST       EQU     400             ; passi extra espulsione cassetta

VEL_REG         DW      1300            ; velocita' tappeto a regime
STEPS_INT       DW      200             ; passi extra dopo sensore centrale

ex              DW      0

; 	riporta lo stato attuale del tappeto dedotto dalla lettura dei sensori
;
; output: ah = 00000XXXb
;                   ³³³
;                   ³³ÀÄÄÄ = stato sensore esterno
;                   ³ÀÄÄÄÄ = stato sensore centrale
;                   ÀÄÄÄÄÄ = stato sensore interno

tappstatus	PROC	NEAR
		xor	ah,ah

                mov     dx,SNS_EST      ; controlla sensore esterno
		in	al,dx
		test	al,SNS_EST_BIT
                jz      ts1             ; sensore a 0
                or      ah,00000001b    ; sensore ad 1

ts1:            mov     dx,SNS_CNT      ; controlla sensore centrale
		in	al,dx
                test    al,SNS_CNT_BIT
                jz      ts2             ; sensore a 0
                or      ah,00000010b    ; sensore ad 1

ts2:            mov     dx,SNS_INT      ; controlla sensore interno
		in	al,dx
		test	al,SNS_INT_BIT
                jz      ts3             ; sensore a 0
		or	ah,00000100b	; sensore ad 1

ts3:            ret
		ENDP

;	muove di un passo il motore del tappeto

tstep		PROC	NEAR
		mov	dx,TCK		; tick
		mov	al,TCK_BIT
		call	reversebit
                mov     cx,vel          ; pausa
		loop	$
		ret
		ENDP

;       porta la cassetta davanti il tappeto
;
; output: param = '0' se tutto ha funzionato a dovere
;         param = 'P' se ancora prima di aver raggiunto il sensore centrale,
;		       si Š eccitato un sensore della pinza
;         param = '1' se ancora prima di aver raggiunto il sensore centrale,
;		       e' stato premuto il tasto Esc
;         param = '2' se ancora prima di aver raggiunto il sensore centrale
;		       e' stato premuto il tasto F9
;         param = 'A' se non Š mai stato raggiunto il sensore centrale
;         param = 'p' se dopo aver raggiunto il sensore centrale, si Š eccitato
;		       un sensore della pinza
;         param = 'B' se non Š mai stato superato il sensore centrale
;         param = 'Q' se dopo aver superato il sensore centrale, questo si Š
;		       eccitato di nuovo
;         param = 'q' se dopo aver superato il sensore centrale, si Š eccitato
;		       un sensore della pinza

__vbtapp        PROC    NEAR
		mov	dx,TDIR			; fissa direzione 1
		mov	al,TDIR_BIT
		call	setbit

		mov	dx,TEN			; attiva motore
		mov	al,TEN_BIT
		call	resetbit

                mov     ax,VEL_REG             ; velocit… di regime
                mov     vel,ax

                mov     dx,SNS_INT              ; controlla sensore interno
                in      al,dx
                test    al,SNS_INT_BIT
                jz      tapp4                   ; sensore eccitato

        ; cassetta davanti sensore centrale

                mov     steps,MAX_STEPS_CNT0    ; massima attesa cassetta

tapp1:          call    tstep                   ; un passo

                mov     dx,SNS_CNT              ; controlla sensore centrale
		in	al,dx
                test    al,SNS_CNT_BIT
		jnz	tapp2			; sensore non eccitato
		mov	cx,WAIT_SNS		; attende stabilit… segnale
		loop	$
		in	al,dx			; verifica sensore
                test    al,SNS_CNT_BIT
		jz	tapp4			; sensore eccitato

tapp2:          mov     dx,BAR_ANT              ; controlla sensori pinza
		in	al,dx
                test    al,BAR_ANT_BIT
                jnz     lp                      ; sensori non eccitati
		mov	cx,WAIT_SNS		; attende stabilit… segnale
		loop	$
                in      al,dx                   ; verifica sensori
                test    al,BAR_ANT_BIT
                jnz     lp                      ; sensori non eccitati
                mov     al,'P'
                jmp     tappret                 ; sensori eccitati

lp:             mov     ah,01h                  ; lettura tastiera al volo
		int	16h
		jz	tapp3			; nessun tasto
		xor	ah,ah			; scarica il buffer
		int	16h
                cmp     ax,ESC_KEY
                jne     tapp31
		mov	al,'1'
                jmp     tappret                 ; ESC
tapp31:         cmp     ax,F9_KEY
                jne     tapp3
		mov	al,'2'
                jmp     tappret                 ; F9

tapp3:          dec     steps                   ; controlla passi totali
                jnz     tapp1                   ; pochi: continua
		mov	al,'A'			; time-out
		jmp	tappret

        ; cassetta dopo sensore centrale

tapp4:          mov     steps,MAX_STEPS_CNT1    ; massima attesa cassetta

tapp5:          call    tstep                   ; un passo

                mov     dx,SNS_CNT              ; controlla sensore centrale
		in	al,dx
                test    al,SNS_CNT_BIT
		jz	tapp6			; sensore eccitato
		mov	cx,WAIT_SNS		; attende stabilit… segnale
		loop	$
		in	al,dx			; verifica sensore
                test    al,SNS_CNT_BIT
                jz      tapp6                   ; sensore eccitato
                mov     dx,SNS_INT              ; controlla barriera interna
                in      al,dx
                test    al,SNS_INT_BIT
                jz      tapp7                   ; barriera interrotta

tapp6:          mov     dx,BAR_ANT              ; controlla sensori pinza
		in	al,dx
                test    al,BAR_ANT_BIT
                jnz     lp1                     ; sensori non eccitati
		mov	cx,WAIT_SNS		; attende stabilit… segnale
		loop	$
                in      al,dx                   ; verifica sensori
                test    al,BAR_ANT_BIT
                jnz     lp1                     ; sensori non eccitati
                mov     al,'p'
                jmp     tappret                 ; sensori eccitati

lp1:            mov     dx,SNS_EST              ; controlla barriera esterna
                in      al,dx
                test    al,SNS_EST_BIT
                jnz     lp11                    ; barriera non interrotta
                mov     dx,SNS_INT              ; controlla barriera interna
                in      al,dx
                test    al,SNS_INT_BIT
                jnz     lp11                    ; barriera non interrotta
                mov     al,'Q'
                jmp     tappret                 ; 3 barriere interrotte

lp11:           dec     steps                   ; controlla passi totali
                jnz     tapp5                   ; pochi: continua
		mov	al,'B'			; time-out
		jmp	tappret

        ; passi extra

tapp7:          mov     ax,STEPS_INT            ; passi dopo sensore
                mov     steps,ax

tapp8:          call    tstep                   ; un passo

                mov     dx,SNS_CNT              ; controlla sensore centrale
		in	al,dx
                test    al,SNS_CNT_BIT
                jnz     lp2                     ; sensore non eccitato
                mov     cx,WAIT_SNS             ; attesa stabilta' segnale
                loop    $
                in      al,dx                   ; verifica sensore
                test    al,SNS_CNT_BIT
                jnz     lp2                     ; sensore non eccitato
		mov	al,'Q'
                jmp     tappret                 ; sensore eccitato

lp2:            mov     dx,BAR_ANT              ; controlla sensori pinza
		in	al,dx
                test    al,BAR_ANT_BIT
                jnz     lp3                     ; sensori non eccitati
                mov     cx,WAIT_SNS             ; attesa stabilita' segnale
                loop    $
                in      al,dx                   ; verifica sensori
                test    al,BAR_ANT_BIT
                jnz     lp3                     ; sensori non eccitati
		mov	al,'q'
                jmp     tappret                 ; sensori eccitati

lp3:            dec     steps                   ; controlla passi fatti
                jnz     tapp8                   ; pochi: continua

		mov	al,'0'			; tutto ok

tappret:	push	ax			; salva esito
		mov	dx,TEN			; disattiva motore
		mov	al,TEN_BIT
		call	setbit
		pop	ax			; ripristina esito
                ret
		ENDP

;       espelle la cassetta
;
; output: param = '0' se tutto ha funzionato a dovere
;         param = 'B' se time-out

esp_stat        DB      ?                       ; stato da raggiungere
esp_max         DW      ?                       ; passi massimi
esp_ex          DW      ?                       ; passi extra

___vbesp        PROC    NEAR
		mov	dx,TDIR			; fissa direzione 0
		mov	al,TDIR_BIT
		call	resetbit

		mov	dx,TEN			; attiva motore
		mov	al,TEN_BIT
		call	resetbit

                mov     ax,VEL_REG             ; velocit… di regime
                mov     vel,ax

                mov     steps,0                 ; passi totali

esp1:           mov     ex,0                    ; passi extra

esp2:           call    tstep                   ; un passo
                inc     steps

                call    tappstatus              ; controlla sensori
                cmp     ah,esp_stat
                jne     esp3                    ; sensori non ok
                inc     ex                      ; controlla passi extra
                mov     ax,ex
                cmp     ax,esp_ex
                jb      esp2                    ; continua
                mov     al,'0'                  ; tutto ok
                jmp     espret

esp3:           mov     ax,steps
                cmp     ax,esp_max              ; controlla passi totali
                jb      esp1                    ; pochi: continua
                mov     al,'B'                  ; time-out

espret:		push	ax			; salva esito
		mov	dx,TEN			; disattiva motore
		mov	al,TEN_BIT
		call	setbit
		pop	ax			; ripristina esito
                ret
		ENDP

__vbesp         PROC    NEAR                    ; espulsione totale
                mov     esp_stat,111b
                mov     esp_max,MAX_STEPS_EST
                mov     esp_ex,STEPS_EST
                jmp     ___vbesp
                ENDP

__vbespp        PROC    NEAR                    ; espulsione parziale, utente batman
                mov     esp_stat,100b
                mov     esp_max,MAX_STEPS_EST
                mov     esp_ex,30
                jmp     ___vbesp
                ENDP

COMMENT ~

;       porta la cassetta davanti il tappeto

__vbtapp        PROC    NEAR
                mov     dx,TEN          ; abilitazione
                mov     al,TEN_BIT
                call    resetbit

                mov     dx,TDIR         ; direzione
                mov     al,TDIR_BIT
                call    setbit

__tapp1:        mov     dx,TCK          ; clock
                mov     al,TCK_BIT
                call    reversebit

                mov     cx,VEL_REG      ; velocita'
                loop    $

                mov     dx,SNS_CNT      ; controlla barriera centrale
                in      al,dx
                test    al,SNS_CNT_BIT
                jnz     __tapp1         ; barriera non interrotta

__tapp2:        mov     dx,TCK          ; clock
                mov     al,TCK_BIT
                call    reversebit

                mov     cx,VEL_REG      ; velocita'
                loop    $

                mov     dx,SNS_CNT      ; controlla barriera interna
                in      al,dx
                test    al,SNS_CNT_BIT
                jz      __tapp2         ; barriera interrotta

                mov     dx,TEN          ; disabilitazione
                mov     al,TEN_BIT
                call    setbit

                mov     al,'0'          ; ok
                ret
                ENDP

;       espelle la cassetta

__vbespp        LABEL   NEAR
__vbesp         PROC    NEAR
                mov     dx,TEN          ; abilitazione
                mov     al,TEN_BIT
                call    resetbit

                mov     dx,TDIR         ; direzione
                mov     al,TDIR_BIT
                call    resetbit

__esp1:         mov     dx,TCK          ; clock
                mov     al,TCK_BIT
                call    reversebit

                mov     cx,VEL_REG      ; velocita'
                loop    $

                mov     dx,SNS_EST      ; controlla barriera esterna
                in      al,dx
                test    al,SNS_EST_BIT
                jnz     __esp1          ; barriera non interrotta

                mov     dx,TEN          ; disabilitazione
                mov     al,TEN_BIT
                call    setbit

                mov     al,'0'          ; ok
                ret
                ENDP

~
;******************************************************************************
;
;	gestione della porta del posto operatore
;
;******************************************************************************

APERTA          EQU     00000010b       ; porta aperta
CHIUSA          EQU     00000001b       ; porta chiusa

pen		DW	0310h  		; segnali motore
pen_bit		DB	00000100b
pdir		DW	031ch
pdir_bit        DB      01000000b       ; 0 -> verso chiusura
pck		DW	0312h
pck_bit		DB	00010000b

pstart_vel      DW      1200            ; parametri rampa velocit…
psteps_acc	DW	1
pacc		DW	0
psteps_decc	DW	1
pdecc		DW	0

sns_inf		DW	0318h		; dati per chiusura porta
sns_inf_bit	DB	00100000b
sns_inf_stat	DB	00000000b
max_steps_down	DW	6000
steps_sns_down  DW      20

sns_sup		DW	0318h		; dati per apertura porta
sns_sup_bit	DB	00010000b
sns_sup_stat	DB	00000000b
max_steps_up	DW	6000
steps_sns_up    DW      40

mgn_blc		DW	0318h		; magnete blocco porta
mgn_blc_bit	DB	00001000b
msns_blc        DW      0318h
msns_blc_bit    DB      01000000b

status          DB      0               ; stato teorico porta (0=aperta, 1=chiusa, 2=incastrata in chiusura)
time1           DW      ?               ; istante chiusura completata se plexiglas e finecorsa sani

;	riporta lo stato attuale della porta dedotto dalla lettura dei sensori
;
; output: ah = 000000XXb
;                    ³ÀÄÄÄ = stato sensore superiore
;                    ÀÄÄÄÄ = stato sensore inferiore

portastatus	PROC	NEAR
		xor	ah,ah

		mov	dx,sns_inf	; controlla sensore inferiore
		in	al,dx
		test	al,sns_inf_bit
		jz	ps1             ; sensore a 0
                or      ah,00000010b    ; sensore ad 1

ps1:		mov	dx,sns_sup	; controlla sensore superiore
		in	al,dx
		test	al,sns_sup_bit
		jz	ps2		; sensore a 0
                or      ah,00000001b    ; sensore ad 1

ps2:            ret
		ENDP

; 	chiude la porta
;
; output: param = '0' se tutto ha funzionato a dovere
;	  param = 'B' se la porta non si Š chiusa nel tempo stabilito
;	  param = 'D' se dopo la chiusura la porta non risultava chiusa

__vbdown        PROC    NEAR
                mov     status,0                ; imposta porta aperta

                mov     di,OFFSET pen           ; chiude
		mov	si,OFFSET sns_inf
		call	motore0
		mov	al,'B'
		jc	downret			; CHIUSURA NON AVVENUTA !!!

        IF INT8 EQ 0                    ; se non c'e' chiusura in background
                call    motoreoff               ; resetta motore (in background)
        ENDIF

                call    portastatus             ; controlla stato porta
		cmp	ah,CHIUSA
		mov	al,'D'
		jne	downret			; PORTA NON CHIUSA !!!

		mov	al,'0'			; tutto ok

                cli
                mov     status,1                ; imposta porta chiusa
                mov     time1,0                 ; registra istante attuale
                sti
                ret

downret:        push    ax                      ; salva esito
                call    motoreoff               ; disabilita motore
                pop     ax                      ; recupera esito
                mov     status,2                ; imposta porta incastrata
                ret
		ENDP

;	apre la porta
;
; output: param = '0' se tutto ha funzionato a dovere
;	  param = 'C' se la porta non si Š aperta nel tempo stabilito
;	  param = 'D' se dopo l'apertura la porta non risultava aperta

__vbup          PROC    NEAR
                mov     status,0                ; imposta porta aperta

                mov     di,OFFSET pen           ; apre
		mov	si,OFFSET sns_sup
		call	motore1
		mov	al,'C'
		jc	upret			; APERTURA NON AVVENUTA !!!

                call    portastatus             ; controlla stato porta
		cmp	ah,APERTA
		mov	al,'D'
		jne	upret			; PORTA NON APERTA !!!

		mov	al,'0'			; tutto ok

upret:          ret
		ENDP

;******************************************************************************
;
;	gestione del gruppo pinza
;
;******************************************************************************

MT0             EQU          ; direzione 0
MT1		EQU		; direzione 1
MAG             EQU          ; pinza davanti magazzino
RIP             EQU         ; pinza a riposo
   RIP_MCR      EQU         
   RIP_MCR_BIT  EQU         
   RIP_MCR_STAT EQU         
   RIP_MAX      EQU         
   RIP_EX       EQU         
TIN             EQU         ; cassetta dentro tappeto
TOUT            EQU         ; cassetta su bordo tappeto
FBR             EQU         ; indirizzo fibra
FBR_BIT         EQU         ; maschera fibra
BAR             EQU         ; indirizzo barriera
BAR_BIT         EQU         ; maschera barriera
MGN             EQU         ; magnete pinza
VICINO          EQU         ; passi vicino magazzino
OTHER           EQU         ; puntatore all'altro magazzino

TNT_PNZ         EQU     3
TNT_PMAG        EQU     15
TNT_INS		EQU	10
TNT_OUT		EQU	10
EX_FIBRA        EQU     100

MCR_ANT         EQU     0310h
MCR_ANT_BIT     EQU     00010000b
MCR_POS         EQU     0316h
MCR_POS_BIT     EQU     00000001b
MCR_CNT         EQU     0310h
MCR_CNT_BIT     EQU     00100000b
IF BARGP EQ 1                                   ; se ci sono le barriere
    BAR_ANT         EQU     0316h               ; le associo ai loro indirizzi
    BAR_ANT_BIT     EQU     00100000b
    BAR_POS         EQU     0316h
    BAR_POS_BIT     EQU     01000000b
ELSE                                            ; se non ci sono le barriere
    BAR_ANT         EQU     FBR_ANT             ; le associo alle fibre
    BAR_ANT_BIT     EQU     FBR_ANT_BIT
    BAR_POS         EQU     FBR_POS
    BAR_POS_BIT     EQU     FBR_POS_BIT
ENDIF
FBR_ANT         EQU     031ah
FBR_ANT_BIT     EQU     01000000b
FBR_POS         EQU     031ah
FBR_POS_BIT     EQU     10000000b
MMCR_ANT        EQU     0316h
MMCR_ANT_BIT    EQU     00001000b
MMCR_POS        EQU     0316h
MMCR_POS_BIT    EQU     00010000b

ppvel           DW      1400
ttvel           DW      1400

				; motore trasporto pinza
ppen		DW	0310h		; segnali motore
ppen_bit	DB	00100000b
ppdir		DW	0314h
ppdir_bit       DB      00001000b       ; 0 -> verso anteriore
ppck		DW	0312h
ppck_bit	DB	10000000b

ppstart_vel     DW      1400            ; parametri rampa velocit…
ppsteps_acc	DW	1
ppacc		DW	0
ppsteps_decc	DW	1
ppdecc		DW	0
				; motore tappeto pinza
tten            DW      0310h           ; segnali motore
tten_bit	DB	00010000b
ttdir		DW	0314h
ttdir_bit       DB      00000100b       ; 0 -> verso posteriore
ttck		DW	0312h
ttck_bit	DB	01000000b

ttstart_vel     DW      1400            ; parametri rampa velocit…
ttsteps_acc	DW	1
ttacc		DW	0
ttsteps_decc	DW	1
ttdecc		DW	0

				; parametri per azioni su magazzino anteriore

mt0_ant		DW	OFFSET motore1  ; direzione motori
mt1_ant		DW	OFFSET motore0

mcr_cnta        DW      MCR_CNT         ; dati per trasporto pinza davanti
mcr_cnta_bit    DB      MCR_CNT_BIT     ; magazzino da posizione di riposo
mcr_cnta_stat   DB      MCR_CNT_BIT
max_steps_ravt	DW	1000
steps_sns_ravt  DW      10

mcr_ant         DW      MCR_POS         ; dati per trasporto pinza in posizione
mcr_ant_bit     DB      MCR_POS_BIT     ; di riposo da magazzino
mcr_ant_stat    DB      MCR_POS_BIT
max_steps_ind	DW	1000
steps_sns_ind   DW      10

IF BARGP EQ 1
    bar_pos0        DW      BAR_POS         ; dati per trasporto cassetta in
    bar_pos0_bit    DB      BAR_POS_BIT     ; centro tappeto da bordo esterno
    bar_pos0_stat   DB      00000000b
ELSE
    bar_pos0        DW      FBR_ANT         ; idem in caso di assenza barriere
    bar_pos0_bit    DB      FBR_ANT_BIT
    bar_pos0_stat   DB      FBR_ANT_BIT
ENDIF
max_steps_aind  DW      3000
steps_sns_aind  DW      10

bar_ant1        DW      BAR_ANT                 ; dati per trasporto cassetta
bar_ant1_bit    DB      BAR_ANT_BIT+BAR_POS_BIT ; da centro tappeto a bordo
bar_ant1_stat   DB      BAR_ANT_BIT+BAR_POS_BIT ; esterno
max_steps_cavt  DW      3000
steps_sns_cavt  DW      10

fbr_ant         DW      FBR_ANT         ; fibra
fbr_ant_bit     DB      FBR_ANT_BIT

bar_ant         DW      BAR_ANT         ; barriera
bar_ant_bit     DB      BAR_ANT_BIT

mgn_ant         DW      0318h           ; magnete pinza
mgn_ant_bit     DB      00100000b
mmcr_ant        DW      MMCR_ANT
mmcr_ant_bit    DB      MMCR_ANT_BIT

vicino_ant      DW      100             ; passi vicino magazzino

othera          DW      OFFSET mt0_pos

				; parametri per azioni su magazzino posteriore

mt0_pos		DW	OFFSET motore0  ; direzione motori
mt1_pos		DW	OFFSET motore1

mcr_cntp        DW      MCR_CNT         ; dati per trasporto pinza davanti
mcr_cntp_bit    DB      MCR_CNT_BIT     ; magazzino da posizione di riposo
mcr_cntp_stat   DB      MCR_CNT_BIT
max_steps_rind	DW	1000
steps_sns_rind  DW      10

mcr_pos         DW      MCR_ANT         ; dati per trasporto pinza in posizione
mcr_pos_bit     DB      MCR_ANT_BIT     ; di riposo da magazzino
mcr_pos_stat    DB      MCR_ANT_BIT
max_steps_avt	DW	1000
steps_sns_avt   DW      10

IF BARGP EQ 1
    bar_ant0        DW      BAR_ANT         ; dati per trasporto cassetta in
    bar_ant0_bit    DB      BAR_ANT_BIT     ; centro tappeto da bordo esterno
    bar_ant0_stat   DB      00000000b
ELSE
    bar_ant0        DW      FBR_POS         ; idem in caso di assenza barriere
    bar_ant0_bit    DB      FBR_POS_BIT
    bar_ant0_stat   DB      FBR_POS_BIT
ENDIF
max_steps_pavt  DW      3000
steps_sns_pavt  DW      10

bar_pos1        DW      BAR_POS                 ; dati per trasporto cassetta
bar_pos1_bit    DB      BAR_POS_BIT+BAR_ANT_BIT ; da centro tappeto a bordo
bar_pos1_stat   DB      BAR_POS_BIT+BAR_ANT_BIT ; esterno
max_steps_cind  DW      3000
steps_sns_cind  DW      10

fbr_pos         DW      FBR_POS         ; fibra
fbr_pos_bit     DB      FBR_POS_BIT

bar_pos         DW      BAR_POS         ; barriera
bar_pos_bit     DB      BAR_POS_BIT

mgn_pos         DW      0318h           ; magnete pinza
mgn_pos_bit     DB      00010000b
mmcr_pos        DW      MMCR_POS
mmcr_pos_bit    DB      MMCR_POS_BIT

vicino_pos      DW      100             ; passi vicino magazzino

otherp          DW      OFFSET mt0_ant

IF BARGP EQ 0                           ; se non ci sono le barriere
    tout0           DW        ?         ; in trasporto cassetta da centro
    tout0_bit       DB        ?         ; a bordo tappeto e' necessario prima
    tout0_stat      DB        00000000b ; eccitare una fibra
    tout0_max       DW        1000
    tout0_ex        DW        50
ENDIF

t               DW      ?

;       riporta in AX la variazione di velocita' del trasporto pinza

ppvelvar        PROC    NEAR
                mov     ax,ppvel
                shr     ax,1
                ret
                ENDP

;       abbassa la velocita' del trasporto

ppslow          PROC    NEAR
                call    ppvelvar
                add     ppstart_vel,ax
                ret
                ENDP

;       aumenta la velocita' del trasporto

ppfast          PROC    NEAR
                call    ppvelvar
                sub     ppstart_vel,ax
                ret
                ENDP

;       riporta in AX la variazione di velocita' del tappeto pinza

ttvelvar        PROC    NEAR
                mov     ax,ttvel
                shr     ax,1
                ret
                ENDP

;       abbassa la velocita' del tappeto

ttslow          PROC    NEAR
                call    ttvelvar
                add     ttstart_vel,ax
                ret
                ENDP

;       aumenta la velocita' del tappeto

ttfast          PROC    NEAR
                call    ttvelvar
                sub     ttstart_vel,ax
                ret
                ENDP

;       riporta in AH lo stato delle barriere
;
; out: bit0 = stato barriera anteriore
;      bit1 = stato barriera posteriore

barstat         PROC    NEAR
                xor     ah,ah           ; inizializza stato

                mov     dx,BAR_ANT      ; controlla barriera anteriore
                in      al,dx
                test    al,BAR_ANT_BIT
                jz      brs1            ; barriera interrotta
                or      ah,01b          ; barriera non interrotta

brs1:           mov     dx,BAR_POS      ; controlla barriera posteriore
                in      al,dx
                test    al,BAR_POS_BIT
                jz      brs2            ; barriera interrotta
                or      ah,10b          ; barriera non interrotta

brs2:           ret                     ; fine
                ENDP

;       riporta in AH lo stato dei micro
;
; out: bit0 = stato micro anteriore
;      bit1 = stato micro centrale
;      bit2 = stato micro posteriore

mcrstat         PROC    NEAR
                xor     ah,ah           ; inizializza stato

                mov     dx,MCR_ANT      ; controlla micro anteriore
                in      al,dx
                test    al,MCR_ANT_BIT
                jz      mrs1            ; micro premuto
                or      ah,001b         ; micro rilasciato

mrs1:           mov     dx,MCR_CNT      ; controlla micro centrale
                in      al,dx
                test    al,MCR_CNT_BIT
                jz      mrs2            ; micro premuto
                or      ah,010b         ; micro rilasciato

mrs2:           mov     dx,MCR_POS      ; controlla micro posteriore
                in      al,dx
                test    al,MCR_POS_BIT
                jz      mrs3            ; micro premuto
                or      ah,100b         ; micro rilasciato

mrs3:           ret                     ; fine
                ENDP

;       cerca di portare il tappeto in posizione di riposo
;
; out: cf = esito (set = negativo, reset = positivo)

taprip          PROC    NEAR
                mov     di,OFFSET tten  ; tappeto pinza

                call    ttslow          ; bassa velocita'

                call    barstat         ; legge stato barriere
                cmp     ah,10b
                je      tprpa           ; cassetta verso anteriore
                cmp     ah,01b
                je      tprpp           ; cassetta verso posteriore

tprpok:         call    ttfast          ; alta velocita'
                clc                     ; ok
                ret

tprpa:          mov     si,OFFSET bar_pos0      ; cassetta in centro da ant.
                call    motore0

                call    barstat                 ; legge stato barriere
        IF BARGP EQ 1
                cmp     ah,00b
        ELSE
                cmp     ah,11b
        ENDIF
                je      tprpok                  ; cassetta in centro
                cmp     ah,01b
                je      tprpok                  ; cassetta verso posteriore
                jmp     tprperr                 ; ERRORE !!!

tprpp:          mov     si,OFFSET bar_ant0      ; cassetta in centro da pos.
                call    motore1

                call    barstat                 ; legge stato barriere
        IF BARGP EQ 1
                cmp     ah,00b
        ELSE
                cmp     ah,11b
        ENDIF
                je      tprpok                  ; cassetta in centro
                cmp     ah,10b
                je      tprpok                  ; cassetta verso anteriore

tprperr:        call    ttfast          ; alta velocita'
                stc                     ; ERRORE !!!
                ret
                ENDP

;       cerca di portare la pinza in posizione di riposo
;
; out: cf = esito (set = negativo, reset = positivo)

pnzrip          PROC    NEAR
                mov     di,OFFSET ppen  ; trasporto pinza

                call    ppslow          ; bassa velocita'

                call    mcrstat         ; legge stato micro
                cmp     ah,100b
                je      pzrpp           ; pinza un po' indietro
                cmp     ah,110b
                je      pzrpp           ; pinza tutta indietro
                cmp     ah,001b
                je      pzrpa           ; pinza un po' avanti
                cmp     ah,011b
                je      pzrpa           ; pinza tutta avanti
                cmp     ah,101b
                je      pzrpok          ; pinza a riposo

pzrperr:        call    ppfast          ; alta velocita'
                stc                     ; ERRORE !!!
                ret

pzrpp:          mov     si,OFFSET mcr_pos       ; pinza a riposo da pos.
                call    motore0

                call    mcrstat                 ; legge stato micro
                cmp     ah,001b
                je      pzrpok                  ; pinza un po' avanti
                cmp     ah,101b
                je      pzrpok                  ; pinza a riposo
                jmp     pzrperr                 ; ERRORE !!!

pzrpa:          mov     si,OFFSET mcr_ant       ; pinza a riposo da ant.
                call    motore1

                call    mcrstat                 ; legge stato micro
                cmp     ah,100b
                je      pzrpok                  ; pinza un po' indietro
                cmp     ah,101b
                je      pzrpok                  ; pinza a riposo
                jmp     pzrperr                 ; ERRORE !!!

pzrpok:         call    ppfast          ; alta velocita'
                clc                     ; ok
                ret
                ENDP

;       cerca di portare la pinza in uno stato stabile e ne riporta l'esito
;
; output: cf = esito (set = negativo, reset = positivo)
;         zf = stato in caso di presenza barriere
;                (set = con cassetta, reset = senza cassetta)

statopinza      PROC    NEAR
                call    pnzrip          ; pinza a riposo
                jc      statoret        ; ERRORE !!!

                call    taprip          ; tappeto a riposo
                jc      statoret        ; ERRORE !!!

        IF BARGP EQ 1                   ; se ci sono le barriere
                call    barstat         ; controlla presenza cassetta
                test    ah,01b
                jz      statook         ; cassetta presente
                test    ah,10b
        ENDIF

statook:        clc                     ; ok

statoret:       ret
                ENDP

;       chiusura pinza

pnz_on          PROC    NEAR
                lea     si,MGN          ; magnete pinza
                mov     cx,TNT_PNZ      ; # tentativi
                jmp     SHORT po2
po1:            push    cx
		call	magneteoff	; apre
		pop	cx
po2:            push    cx
		call	magneteon	; chiude
		pop	cx
          IF SNSPNC EQ 1                ; se i magneti hanno i micro
                jnz     po3             ; pinza chiusa
          ELSE                          ; altrimenti ci sono i prossimetri
                jz      po3             ; pinza chiusa
          ENDIF
                loop    po1
po3:            ret
                ENDP

;       apertura pinza

ver_pnz         DB      ?               ; flag di verifica apertura pinza
                                        ; (1=pinza aperta,0=pinza chiusa)

pnz_off         PROC    NEAR
                lea     si,MGN          ; magnete pinza
                call    magneteoff      ; apre
                mov     ver_pnz,1       ; imposta apertura avvenuta
        IF SNSPNC EQ 1                  ; se i magneti hanno i micro
                jz      pnzor           ; pinza aperta
        ELSE                            ; altrimenti ci sono i prossimetri
                jnz     pnzor           ; pinza aperta
        ENDIF
                mov     ver_pnz,0       ; imposta apertura fallita
pnzor:          ret
                ENDP

;       pinzata da magazzino
;
; output: zf = stato della barriera

pinzata_mag     PROC    NEAR
                mov     di,OFFSET ppen  ; pinza davanti magazzino
                lea     si,MAG
		call	MT1

                call    pnz_on          ; chiusura pinza

                mov     dx,ttdir        ; dir. tapp. (verso mag. opposto)
		mov	al,ttdir_bit
                call    setbit          ; verso anteriore
                cmp     word ptr MT1,OFFSET motore1
                je      pm1
                mov     dx,ttdir
                mov     al,ttdir_bit
		call	resetbit	; verso posteriore

pm1:            mov     al,ttck_bit     ; pinza a riposo con rotazione tappeto
		or	ppck_bit,al
                lea     si,RIP
		call	MT0
		mov	al,ttck_bit
		not	al
		and	ppck_bit,al

                call    pnz_off         ; apertura pinza

                mov     dx,BAR          ; controllo barriera
                in      al,dx
                test    al,BAR_BIT
                ret
		ENDP

;       pinzata da tappeto
;
; output: zf = esito (set -> ok, reset -> si richiede ulteriore pinzata)

fibra           DW      ?
totrip          DW      ?
exrip           DW      ?

ind             DB      ? ; flag di indietreggiamento:
                          ; 0 -> non indietreggiare, 1 -> indietreggiare

STEPSIND        DW      30      ; passi indietro dopo apertura pinza e prima
                                ; di controllare la fibra su magazzino

pinzata_tap     PROC    NEAR
                call    pnz_on          ; chiusura pinza

                mov     dx,ttdir        ; dir. tapp. (verso mag.)
		mov	al,ttdir_bit
                call    setbit          ; verso anteriore
                cmp     word ptr MT0,OFFSET motore1
                je      _pt1
                mov     dx,ttdir
                mov     al,ttdir_bit
		call	resetbit	; verso posteriore

_pt1:           mov     al,ttck_bit     ; pinza su mag. con rotazione tappeto
		or	ppck_bit,al
		mov	di,OFFSET ppen
                lea     si,MAG
		call	MT1
		mov	al,ttck_bit
		not	al
		and	ppck_bit,al

                cmp     ind,5           ; controlla indietreggiamento
                jb      no_ind          ; indietreggiamento non attivo

                mov     ax,2            ; attende un po'
__pt1:          xor     cx,cx
                loop    $
                dec     ax
                jnz     __pt1

                call    pnz_off         ; apertura pinza

                                        ; pinza un po' indietro lentamente
                mov     dx,ppdir        ;   inverte direzione
                mov     al,ppdir_bit
                call    reversebit
                call    ppslow          ;   bassa velocita'
                mov     cx,STEPSIND     ;   passi da fare
                call    stepss          ;   muove
                call    ppfast          ;   alta velocita'

                mov     ax,2            ; attende un po'
___pt1:         xor     cx,cx
                loop    $
                dec     ax
                jnz     ___pt1

                mov     fibra,0         ; imposta fibra diseccitata
                mov     dx,FBR          ; controlla fibra
                in      al,dx
                test    al,FBR_BIT
                jnz     _pt2            ; fibra diseccitata
                mov     fibra,1         ; imposta fibra eccitata
                jmp     _pt2

no_ind:         mov     fibra,0         ; imposta fibra diseccitata
                mov     dx,FBR          ; controlla fibra
                in      al,dx
                test    al,FBR_BIT
                jnz     __pt2           ; fibra diseccitata
                mov     fibra,1         ; imposta fibra eccitata

__pt2:          call    pnz_off         ; apertura pinza

                mov     dx,ppdir        ; inverte direzione trasporto pinza
                mov     al,ppdir_bit
                call    reversebit

        ; riporta la pinza in posizione di riposo

_pt2:           mov     totrip,0        ; passi totali
                mov     exrip,0         ; passi extra

_pt3:           mov     dx,ppck         ; un passo
                mov     al,ppck_bit
                call    reversebit
                mov     cx,ppstart_vel
                loop    $
                inc     totrip

                mov     dx,RIP_MCR      ; controlla stato di riposo
                in      al,dx
                and     al,RIP_MCR_BIT
                xor     al,RIP_MCR_STAT
                jnz     _pt4            ; stato non raggiunto

                inc     exrip           ; controlla passi extra
                mov     ax,exrip
                cmp     ax,RIP_EX
                jbe     _pt5            ; pochi: continua

                mov     cx,WAIT_SNS     ; attende stabilita' segnale
                loop    $

                in      al,dx           ; verifica stato di riposo
                and     al,RIP_MCR_BIT
                xor     al,RIP_MCR_STAT
                jz      _ptret          ; stato raggiunto

_pt4:           mov     exrip,0
                mov     ax,totrip       ; controlla passi totali
                cmp     ax,RIP_MAX
                jae     _ptret          ; troppi: time-out !!!

_pt5:           mov     dx,FBR          ; controlla fibra
                in      al,dx
                test    al,FBR_BIT
                jnz     _pt6            ; fibra non eccitata

                mov     fibra,1         ; imposta fibra eccitata
                jmp     _pt3            ; continua

_pt6:           cmp     fibra,0         ; controlla storico fibra
                je      _pt3            ; fibra non eccitata: continua

                inc     fibra           ; fibra diseccitata
                cmp     fibra,EX_FIBRA  ; da quanto ?
                jb      _pt3            ; da poco: continua

_ptret:         cmp     fibra,0         ; imposta valore di ritorno
                ret
                ENDP

;       verifica la presenza della cassetta in magazzino
;
; out: cf = esito (set -> negativo, reset -> positivo)

STEPSVER        EQU     150
STEPSVER1       EQU     300

verifica        PROC    NEAR
                mov     di,OFFSET ppen  ; pinza davanti magazzino
                lea     si,MAG
		call	MT1

                call    pnz_on          ; chiusura pinza

                                        ; pinza un po' indietro
                mov     dx,ppdir        ;   inverte direzione
                mov     al,ppdir_bit
                call    reversebit
                mov     cx,STEPSVER     ;   passi da fare
                call    stepss          ;   muove

                call    pnz_off         ; apertura pinza

                mov     di,OFFSET ppen  ; pinza davanti magazzino
                lea     si,MAG
		call	MT1

                and     fibra,110b      ; imposta fibra eccitata
                mov     dx,FBR          ; controlla fibra
                in      al,dx
                test    al,FBR_BIT
                jz      ver0            ; fibra eccitata
                or      fibra,001b      ; imposta fibra non eccitata

ver0:           and     fibra,011b      ; azzera tentativi

                                        ; riporta la pinza un po' indietro
ver1:           mov     dx,ppdir        ;   inverte direzione
                mov     al,ppdir_bit
                call    reversebit
                mov     cx,STEPSVER1    ;   passi da fare
                call    stepss          ;   muove

                call    pnz_on          ; chiusura pinza

                mov     di,OFFSET ppen  ; pinza davanti magazzino
                lea     si,MAG
		call	MT1

                and     fibra,101b      ; imposta fibra diseccitata
                mov     dx,FBR          ; controlla fibra
                in      al,dx
                test    al,FBR_BIT
                jnz     ver2            ; fibra non eccitata
                or      fibra,010b      ; imposta fibra eccitata
                xor     fibra,100b      ; incrementa tentativi

ver2:           call    pnz_off         ; apertura pinza

                test    fibra,010b      ; testa stato fibra
                jz      ver3            ; fibra non eccitata
                test    fibra,100b      ; controlla tentativi fatti
                jnz     ver1            ; pochi: riprova
                stc                     ; ERRORE: FIBRA ECCITATA !!!
                jmp     verret

ver3:           test    fibra,001b      ; testa stato fibra precedente
                stc
                jnz     verret          ; ERRORE: FIBRA NON ECCITATA !!!
                clc                     ; ok

verret:         pushf                   ; salva esito
                mov     di,OFFSET ppen  ; pinza a riposo
                lea     si,RIP
                call    MT0
                popf                    ; recupera esito
                ret
                ENDP

;       prelievo cassetta da bordo tappeto
;
; output: cf = esito (set = negativo, reset = positivo)

inside          PROC    NEAR
                mov     cx,TNT_INS      ; # tentativi
                jmp     SHORT in2
in1:            push    cx              ; pinzata da magazzino
                call    pinzata_mag
                pop     cx
in2:            push    cx              ; cassetta in centro tappeto
		mov	di,OFFSET tten
                lea     si,TIN
		call	MT1
		pop	cx
		jnc	insret		; cassetta in centro
                loop    in1             ; riprova
                stc                     ; time-out
insret:		ret
		ENDP

;       deposito cassetta da bordo tappeto
;
; output: cf = esito (set = time-out, reset = ok)

outside		PROC	NEAR
                mov     cx,TNT_OUT      ; contatore tentativi
                mov     ind,0           ; disattiva indietreggiamento

_out00:         inc     ind             ; imposta riprova per fibra eccitata

_out0:          push    cx              ; salva contatore
                call    pinzata_tap     ; pinzata da tappeto
                pop     cx              ; recupera contatote

                mov     ah,0            ; imposta esito pinzata positivo
                jz      _out1           ; esito positivo
                or      ah,00000001b    ; imposta esito pinzata negativo

_out1:          mov     dx,BAR_ANT      ; controlla barriera anteriore
                in      al,dx
                test    al,BAR_ANT_BIT
                jnz     _out2           ; barriera non interrotta
                or      ah,00000010b    ; barriera interrotta

_out2:          mov     dx,BAR_POS      ; controlla barriera posteriore
                in      al,dx
                test    al,BAR_POS_BIT
                jnz     _out3           ; barriera non interrotta
                or      ah,00000010b    ; barriera interrotta

_out3:          or      ah,ah           ; controlla esito generale
                jz      _outok
                dec     cx              ; controlla tentativi
                stc
                jz      _outret         ; troppi: time-out !!!

                test    ah,00000010b    ; controlla stato barriere
                jz      _out00          ; non interrotte: continua
                push    cx              ; salva contatore
                mov     di,OFFSET tten  ; motore tappeto

        IF BARGP EQ 0                      ; se non ci sono le barriere,
                mov     ax,FBR             ; prima eccita una fibra
                mov     tout0,ax
                mov     al,FBR_BIT
                mov     tout0_bit,al
                mov     si,OFFSET tout0
                call    MT0
        ENDIF

                lea     si,TOUT         ; tappeto verso esterno
		call	MT0
                pop     cx              ; recupera contatore
                jmp     _out0           ; continua

_outok:
        IF VERPNZ EQ 1
                cmp     ver_pnz,1       ; controlla pinza aperta
                clc
                je      _outret         ; tutto ok
                call    verifica        ; verifica pinza in magazzino
        ELSE
                clc                     ; tutto ok
        ENDIF

_outret:        ret
                ENDP

;	preleva la cassetta dal magazzino
;
; output: AL = '0' = tutto ok
;              'G' = cassetta assente o presa fallita
;              'F' = stato errato dopo constatazione cassetta assente
;              'J' = prelievo e deposito falliti
;              'K' = prelievo fallito ma deposito riuscito
;              'I' = stato errato dopo prelievo o deposito riusciti

pop		PROC    NEAR
                call    pinzata_mag     ; avvicina la cassetta

                mov     cx,TNT_PMAG     ; numero tentativi
pop1:           push    cx
                call    pinzata_mag     ; pinza la cassetta
		pop	cx
                jz      pop3            ; barriera eccitata
		loop    pop1		; riprova

                call    statopinza      ; controlla stato gruppo pinza
                mov     al,'F'
                jc      pop2            ; STATO ERRATO !!!
        IF BARGP EQ 1
                jz      pop2            ; STATO ERRATO !!!
        ENDIF
		mov	al,'G'		; CASSETTA ASSENTE !!!
pop2:           ret

pop3:           call    inside          ; porta la cassetta al centro
                jnc     pop5            ; ok

		call	outside		; deposita la cassetta
                mov     al,'J'
                jc      pop4            ; DEPOSITO E PRELIEVO FALLITI !!!
                call    statopinza      ; controlla stato pinza
                mov     al,'I'
                jc      pop4            ; STATO ERRATO !!!
        IF BARGP EQ 1
                jz      pop4            ; STATO ERRATO !!!
        ENDIF
                mov     al,'K'          ; prelievo fallito ma deposito ok
pop4:           ret

pop5:           call    statopinza      ; controlla stato pinza
                mov     al,'I'
                jc      pop6            ; STATO ERRATO !!!
        IF BARGP EQ 1
                jnz     pop6            ; STATO ERRATO !!!
        ENDIF
		mov	al,'0'		; tutto ok
pop6:           ret
		ENDP

;       deposita la cassetta in magazzino
;
; output: AL = '0' = tutto ok
;              'S' = stato errato dopo deposito o prelievo riuscito
;              'V' = deposito e prelievo falliti
;              'U' = deposito fallito ma prelievo riuscito

push            PROC    NEAR
                mov     di,OFFSET tten  ; motore tappeto

        IF BARGP EQ 0                      ; se non ci sono le barriere,
                mov     ax,FBR             ; prima eccita una fibra
                mov     tout0,ax
                mov     al,FBR_BIT
                mov     tout0_bit,al
                mov     si,OFFSET tout0
                call    MT0
        ENDIF

                lea     si,TOUT         ; cassetta su bordo tappeto
                call    MT0

                call    outside         ; tenta deposito
                jc      push2           ; deposito non riuscito

                call    statopinza      ; controlla stato gruppo pinza
                mov     al,'S'
                jc      push1           ; STATO ERRATO !!!
        IF BARGP EQ 1
                jz      push1           ; STATO ERRATO !!!
        ENDIF
		mov	al,'0'		; tutto ok
push1:          ret

push2:          mov     cx,TNT_PMAG
push22:         mov     dx,BAR          ; controlla barriera
                in      al,dx
                test    al,BAR_BIT
                jz      push222         ; barriera eccitata
                dec     cx              ; controlla tentativi
                mov     al,'V'
                jz      push3           ; troppi: DEPOSITO E PRELIEVO FALLITI
                push    cx              ; salva contatore
                call    pinzata_mag     ; pinzata da magazzino
                pop     cx              ; recupera contatore
                jmp     push22          ; ricontrolla

push222:        call    inside          ; tenta prelievo
                mov     al,'V'
                jc      push3           ; DEPOSITO E PRELIEVO FALLITI !!!
                call    statopinza      ; controlla stato pinza
                mov     al,'S'
                jc      push3           ; STATO ERRATO !!!
        IF BARGP EQ 1
                jnz     push3           ; STATO ERRATO !!!
        ENDIF
                mov     al,'U'          ; deposito fallito ma prelievo ok
push3:          ret
                ENDP

;	preleva/restituisce la cassetta dal/nel magazzino specificato
;
; input: param = 'A' se prelievo/restituzione dal/nel magazzino anteriore
;	 param = 'P' se prelievo/restituzione dal/nel magazzino posteriore
;
; output: param = codice di errore

__vbpick        PROC    NEAR
                mov     bx,OFFSET pop
                jmp     SHORT prgo

__vbplace       LABEL    NEAR
                mov     bx,OFFSET push

prgo:           push    bp

		mov	bp,OFFSET mt0_ant	; dal/nel magazzino anteriore
		cmp	al,'A'
		je      prg1
                mov     bp,OFFSET mt0_pos       ; dal/nel magazzino posteriore

prg1:           push    bx
                mov     di,OFFSET tten          ; abilita motori
		call	motoreon
                mov     di,OFFSET ppen
                call    motoreon
		pop	bx

                call    bx                      ; preleva/restituisce
                xor     cx,cx                   ; attesa
                loop    $

		push	ax			; salva esito
		mov	di,OFFSET ppen		; disattiva motori
		call	motoreoff
		mov	di,OFFSET tten
		call	motoreoff
		pop	ax			; recupera esito

		pop	bp
                ret
		ENDP

STEPS_ANT       DW     200     ; passi in deposito su tappeto
STEPST          DW     70      ; passi pinza da riposo a tappeto
STEPSP          DW     70      ; passi pinza da riposo a posteriore

MAX_TNT         EQU     10     ; tentativi pinzate su tappeto

tttstep		PROC	NEAR		; muove di un passo i tappeti
		mov	dx,ttck			; tick
		mov	al,01100000b
		call	reversebit
		mov	cx,vel			; velocit…
		loop	$
		ret
		ENDP

dir0            PROC    NEAR            ; direzione verso tappeto
                mov     dx,ppdir
                mov     al,ppdir_bit
                call    resetbit
                ret
                ENDP

dir1            PROC    NEAR            ; direzione verso posteriore
                mov     dx,ppdir
                mov     al,ppdir_bit
                call    setbit
                ret
                ENDP

cktton          PROC    NEAR            ; abilita rotazione tappeti con pinza
                mov     al,TCK_BIT
                or      al,ttck_bit
                or      ppck_bit,al
                ret
                ENDP

ckttoff         PROC    NEAR            ; disabilita tappeti con pinza
                mov     al,TCK_BIT
                or      al,ttck_bit
                not     al
                and     ppck_bit,al
                ret
                ENDP

stepss          PROC    NEAR            ; cx passi su trasporto
                mov     dx,ppck         ; tick
                mov     al,ppck_bit
                call    reversebit
                push    cx              ; delay
                mov     cx,ppstart_vel
                loop    $
                pop     cx
                loop    stepss          ; prossimo
                ret
                ENDP

pnzon           PROC    NEAR            ; chiusura pinza anteriore
                push    bp
                mov     bp,OFFSET mt0_ant
                call    pnz_on
                pop     bp
                ret
                ENDP

pnzoff          PROC    NEAR            ; apertura pinza anteriore
                push    bp
                mov     bp,OFFSET mt0_ant
                call    pnz_off
                pop     bp
                ret
                ENDP

pick            PROC    NEAR            ; presa cassetta
                call    dir0            ; direzione verso tappeto

                mov     cx,STEPST       ; pinza su tappeto
                call    stepss

                call    pnzon           ; chiusura pinza

                call    dir1            ; direzione verso posteriore

                call    cktton          ; associa tappeti

                mov     cx,STEPST       ; pinza su posteriore
                add     cx,STEPSP
                call    stepss

                call    ckttoff         ; dissocia tappeti

                call    pnzoff          ; apertura pinza

                mov     di,OFFSET ppen          ; pinza a riposo
                mov     si,OFFSET mcr_pos
                call    motore0

                ret
                ENDP

place           PROC    NEAR            ; deposito cassetta
                call    dir1            ; direzione verso posteriore

                mov     cx,STEPSP       ; pinza su posteriore
                call    stepss

                call    pnzon           ; chiusura pinza

                call    dir0            ; direzione verso tappeto

                call    cktton          ; associa tappeti

                mov     cx,STEPSP       ; pinza su tappeto
                add     cx,STEPST
                call    stepss

                call    ckttoff         ; dissocia tappeti

                call    pnzoff          ; apertura pinza

                mov     di,OFFSET ppen          ; pinza a riposo
                mov     si,OFFSET mcr_ant
                call    motore1

                ret
                ENDP

;	preleva la cassetta dal tappeto (casella 0)
;
; output: AL = '0' -> tutto ok
;              'B' -> time-out
;              'I' -> barriera centrale interrotta prima di quella anteriore
;              'i' -> barriera cnt. int. assieme a quella anteriore

IF BARGP EQ 0
    fbr_stat    DB      ?
ENDIF

__vbpicktp      PROC    NEAR
                mov     di,OFFSET ppen          ; abilita tappeti e pinza
                call    motoreon
                mov     dx,TEN
		mov	al,TEN_BIT
		call	resetbit
		mov	di,OFFSET tten
		call	motoreon

		mov	dx,TDIR			; direzione 1 per tappeto p.o.
		mov	al,TDIR_BIT
		call    setbit
		mov	dx,ttdir		; direzione 0 per tappeto pinza
		mov	al,ttdir_bit
		call	resetbit

                mov     ax,VEL_REG              ; velocit… di regime
                mov     vel,ax

                mov     t,0                     ; # tentativi

        IF BARGP EQ 0
                mov     fbr_stat,0              ; attende fibra eccitata
        ENDIF

pt1:            mov     steps,0                 ; passi totali

pt2:            mov     ex,0                    ; passi extra

pt3:            call    tttstep                 ; un passo
                inc     steps

                mov     dx,SNS_CNT              ; controllo barriera centrale
                in      al,dx
                test    al,SNS_CNT_BIT
                jnz     pt4                     ; barriera non interrotta
                mov     dx,SNS_EST              ; controllo barriera esterna
                in      al,dx
                test    al,SNS_EST_BIT
                jnz     pt4                     ; barriera non interrotta

                mov     cx,WAIT_SNS             ; attende stabilita'
                loop    $

                mov     dx,SNS_CNT              ; verifica barriera centrale
                in      al,dx
                test    al,SNS_CNT_BIT
                jnz     pt4                     ; barriera non interrotta
                mov     dx,SNS_EST              ; verifica barriera esterna
                in      al,dx
                test    al,SNS_EST_BIT
                jnz     pt4                     ; barriera non interrotta

                mov     dx,BAR_ANT              ; controllo barriera anteriore
                in      al,dx
                test    al,BAR_ANT_BIT
                mov     al,'I'                  ; non interrotta
                jnz     ptret
                mov     al,'i'                  ; interrotta
                jmp     ptret

pt4:
        IF BARGP EQ 1
                mov     dx,BAR_POS              ; controllo barriera posteriore
                in      al,dx
                test    al,BAR_POS_BIT
                jnz     pt5                     ; barriera non eccitata
         ;      mov     dx,BAR_ANT              ; controlla barriera anteriore
         ;      in      al,dx
         ;      test    al,BAR_ANT_BIT
         ;      jnz     pt5                     ; barriera non eccitata
        ELSE
                mov     dx,FBR_ANT              ; controlla barriera interna
                in      al,dx
                and     al,FBR_ANT_BIT
                xor     al,fbr_stat
                jnz     pt5                     ; barriera non raggiunta
        ENDIF

                inc     ex                      ; controllo passi extra
                mov     ax,ex
                cmp     ax,steps_sns_aind
                jb      pt3                     ; continua

                mov     cx,WAIT_SNS             ; attende stabilita'
                loop    $

        IF BARGP EQ 1
                mov     dx,BAR_POS              ; verifica barriera posteriore
                in      al,dx
                test    al,BAR_POS_BIT
                jnz     pt5                     ; barriera non eccitata
         ;      mov     dx,BAR_ANT              ; verifica barriera anteriore
         ;      in      al,dx
         ;      test    al,BAR_ANT_BIT
         ;      jnz     pt5                     ; barriera non eccitata
        ELSE
                mov     dx,FBR_ANT              ; verifica barriera interna
                in      al,dx
                and     al,FBR_ANT_BIT
                xor     al,fbr_stat
                jnz     pt5                     ; barriera non raggiunta
                xor     fbr_stat,FBR_ANT_BIT    ; inverte stato da raggiungere
                jnz     pt1                     ; continua
        ENDIF

                mov     al,'0'                  ; tutto ok
                jmp     ptret

pt5:            mov     ax,steps
                cmp     ax,max_steps_aind       ; controllo passi totali
                jb      pt2                     ; continua
                cmp     t,MAX_TNT               ; controlla tentativi
                mov     al,'B'
                jae     ptret                   ; time-out
                call    pick                    ; pinzata
                inc     t
                jmp     pt1                     ; riprova

ptret:		push	ax			; salva esito
                mov     dx,ppen                 ; disabilita tappeti e pinza
                mov     al,ppen_bit
                call    setbit
                mov     dx,TEN
		mov	al,TEN_BIT
		call	setbit
		mov	di,OFFSET tten
		call	motoreoff
		pop	ax			; recupera esito
                ret
		ENDP

;	pone la cassetta sul tappeto (casella 0)
;
; output: AL = '0' -> tutto ok
;              'A' -> time-out
;              'B' -> cassetta in tappeto ma ancora visibile da pinza
;              'C' -> cassetta non vista da pinza e neanche in tappeto

presente        DB      ? ; flag di rilevazione passaggio cassetta
stato           DB      ? ; stato attuale barriere
ex_pnz          DW      ? ; passi extra barriere pinza diseccitate
ex_cnt          DW      ? ; passi extra barriera centrale eccitata

__vbpltp        PROC    NEAR
                mov     di,OFFSET ppen  ; abilita tappeti e pinza
                call    motoreon
                mov     dx,TEN
		mov	al,TEN_BIT
		call	resetbit
		mov	di,OFFSET tten
		call	motoreon

                mov     dx,TDIR         ; direzione 0 per tappeto p.o.
		mov	al,TDIR_BIT
                call    resetbit
                mov     dx,ttdir        ; direzione 1 per tappeto pinza
		mov	al,ttdir_bit
                call    setbit

                mov     ax,VEL_REG      ; velocit… di regime
                mov     vel,ax

                mov     t,0             ; # tentativi

                mov     presente,000b   ; imposta cassetta non vista

pl1:            mov     steps,0         ; passi totali

                mov     ex_pnz,0        ; passi extra
                mov     ex_cnt,0

pl3:            call    tttstep         ; un passo
                inc     steps           ; incrementa contatore passi totali

        ;       mov     dx,BAR_POS      ; controlla barriera posteriore
        ;       in      al,dx
        ;       test    al,BAR_POS_BIT
        ;       jz      pl4             ; barriera interrotta
                mov     dx,BAR_ANT      ; controlla barriera anteriore
                in      al,dx
                test    al,BAR_ANT_BIT
                jz      pl4             ; barriera interrotta

                or      stato,001b      ; impone: barriere pinza = non interr.
                inc     ex_pnz          ; incrementa contatore passi extra ...
                cmp     ex_pnz,500      ; ... limitando l'overflow
                jbe     pl5
                dec     ex_pnz
                jmp     pl5

pl4:            or      presente,001b   ; impone: cassetta vista da barr. pnz.
                and     stato,110b      ; impone: barriere pinza = interr.
                mov     ex_pnz,0        ; azzera contatore passi extra

pl5:            mov     dx,SNS_INT      ; controlla barriera interna
                in      al,dx
                test    al,SNS_INT_BIT
                jz      pl6             ; barriera interrotta

                or      stato,010b      ; impone: barriera interna = non int.
                jmp     pl7

pl6:            or      presente,010b   ; impone: cassetta vista da barr. int.
                and     stato,101b      ; impone: barriera interna interrotta

pl7:            mov     dx,SNS_CNT      ; controlla barriera centrale
                in      al,dx
                test    al,SNS_CNT_BIT
                jz      pl8             ; barriera interrotta

                or      stato,100b      ; impone: barriera centrale = non int.
                mov     ex_cnt,0        ; azzera contatore passi extra
                jmp     pl9

pl8:            or      presente,100b   ; impone: cassetta vista da barr. cnt.
                and     stato,011b      ; impone: barriera centrale = int.
                inc     ex_cnt          ; incrementa contatore passi extra ...
                cmp     ex_cnt,20       ; ... evitando l'overflow
                jbe     pl9
                dec     ex_cnt

pl9:            test    stato,001b      ; ceck barriere pinza
                jnz     pl12            ; barriere non interrotte

                test    stato,010b      ; ceck barriera interna
                jz      pl10            ; barriera interrotta

                test    presente,010b   ; cassetta vista su barr. interna ?
                jz      pl10            ; no: continua

                test    stato,100b      ; ceck barriere centrale
                jnz     pl10            ; barriera non interrotta

                mov     al,'B'          ; CASSETTA VISIBILE DA TAPP. E PNZ. !!
                jmp     plret

pl10:           cmp     steps,2000      ; controlla passi totali
                jae     pl33            ; troppi
                jmp     pl3             ; pochi: continua

pl33:           cmp     t,MAX_TNT       ; controlla tentativi pinzata
                jb      pl11            ; pochi: continua

                mov     al,'A'          ; TIME-OUT !!!
                jmp     plret

pl11:           call    place           ; pinzata
                inc     t
                jmp     pl1             ; riprova

pl12:           cmp     ex_pnz,500      ; da quanto bar. pnz. non interr. ?
                jae     pl333           ; da molto
                jmp     pl3             ; da poco: continua

pl333:          test    stato,010b      ; ceck barriera interna
                jnz     pl13            ; barriera non interrotta

                test    stato,100b      ; ceck barriera centrale
                jnz     pl10            ; barriera non interrotta

                cmp     ex_cnt,20       ; da quanto bar. cnt. interrotta ?
                jae     pl13            ; da molto
                jmp     pl3             ; da poco: coninua

pl13:   IF BARGP EQ 0                   ; verifica deposito avvenuto

                test    presente,001b   ; cassetta vista su barriere pinza ?
                jz      pl14            ; no: verifica

                jmp     plok            ; si: fine

pl14:           call    dir1            ; pinza su mag. post.
                mov     cx,STEPSP
                call    stepss

                mov     ax,3            ; piccola attesa
llll1:          xor     cx,cx
                loop    $
                dec     ax
                jnz     llll1

                mov     dx,FBR_ANT      ; controlla fibra anteriore
                in      al,dx
                test    al,FBR_ANT_BIT
                jnz     __pl1           ; fibra non eccitata

                cmp     t,MAX_TNT       ; controlla tentativi
                jb      __pl0           ; pochi

                mov     di,OFFSET ppen  ; pinza a riposo
                mov     si,OFFSET mcr_pos
                call    motore0

                mov     al,'A'          ; time-out !!!
                jmp     plret

__pl0:          call    pnzon           ; chiusura pinza

                call    dir0            ; direzione verso tappeto

                call    cktton          ; associa tappeti

                mov     cx,STEPSP       ; pinza su tappeto
                add     cx,STEPST
                call    stepss

                call    ckttoff         ; dissocia tappeti

                call    pnzoff          ; apertura pinza

                mov     di,OFFSET ppen  ; pinza a riposo
                mov     si,OFFSET mcr_ant
                call    motore1

                inc     t

                jmp     pl1             ; riprova

__pl1:          call    dir0            ; pinza su tappeto p.o.
                mov     cx,STEPSP
                add     cx,STEPST
                call    stepss

                mov     ax,3            ; piccola attesa
llll2:          xor     cx,cx
                loop    $
                dec     ax
                jnz     llll2

                mov     dx,FBR_POS      ; controlla fibra posteriore
                in      al,dx
                test    al,FBR_POS_BIT
                jnz     __pl2           ; fibra non eccitata

                cmp     t,MAX_TNT       ; controlla tentativi
                jb      __pl00          ; pochi

                mov     di,OFFSET ppen  ; pinza a riposo
                mov     si,OFFSET mcr_ant
                call    motore1

                mov     al,'A'          ; time-out !!!
                jmp     plret

__pl00:         mov     di,OFFSET ppen  ; pinza a riposo
                mov     si,OFFSET mcr_ant
                call    motore1

                call    place           ; pinzata
                inc     t

                jmp     pl1             ; riprova

__pl2:          mov     di,OFFSET ppen  ; pinza a riposo
                mov     si,OFFSET mcr_ant
                call    motore1

                test    presente,010b   ; cassetta vista su barriera interna ?
                jnz     plok            ; si: ok

                cmp     t,5             ; controlla tentativi pinzata
                jb      __pl3

                mov     al,'C'          ; CASSETTA ASSENTE O MAI VISTA !!!
                jmp     plret

__pl3:          call    place           ; pinzata
                inc     t
                jmp     pl1             ; riprova

        ENDIF

plok:           mov     al,'0'                  ; tutto ok

plret:          push    ax                      ; salva esito
                mov     dx,ppen                 ; disabilita tappeti e pinza
                mov     al,ppen_bit
                call    setbit
                mov     dx,TEN
		mov	al,TEN_BIT
		call	setbit
		mov	di,OFFSET tten
		call	motoreoff
		pop	ax			; recupera esito
                ret
                ENDP

COMMENT ~

;	pone la cassetta sul tappeto (casella 0)
;
; output: AL = '0' -> tutto ok
;              'A' -> time-out

__vbpltp        PROC    NEAR
                mov     di,OFFSET ppen          ; abilita tappeti e pinza
                call    motoreon
                mov     dx,TEN
		mov	al,TEN_BIT
		call	resetbit
		mov	di,OFFSET tten
		call	motoreon

                mov     dx,TDIR                 ; direzione 0 per tappeto p.o.
		mov	al,TDIR_BIT
                call    resetbit
                mov     dx,ttdir                ; direzione 1 per tappeto pinza
		mov	al,ttdir_bit
                call    setbit

                mov     ax,VEL_REG              ; velocit… di regime
                mov     vel,ax

                mov     t,0                     ; # tentativi

        IF BARGP EQ 0
                mov     fbr_stat,0              ; attesa fibra eccitata

                mov     dx,SNS_INT              ; controlla barriera interna
                in      al,dx
                test    al,SNS_INT_BIT
                jnz     pl1                     ; barriera non interrotta
                mov     fbr_stat,FBR_ANT_BIT    ; barriera interrotta -> attesa fibra diseccitata
        ENDIF

pl1:            mov     steps,0                 ; passi totali

pl2:            mov     ex,0                    ; passi extra

pl3:            call    tttstep                 ; un passo
                inc     steps

        IF BARGP EQ 1
                mov     dx,BAR_POS              ; controllo bar. pos.
                in      al,dx
                test    al,BAR_POS_BIT
                jz      pl4                     ; bar. interrotta
                mov     dx,BAR_ANT              ; controllo bar. ant.
                in      al,dx
                test    al,BAR_ANT_BIT
                jz      pl4                     ; bar. interrotta
        ELSE
                mov     dx,FBR_ANT              ; controlla fibra anteriore
                in      al,dx
                and     al,FBR_ANT_BIT
                xor     al,fbr_stat
                jnz     pl4                     ; fibra non raggiunta
                cmp     fbr_stat,FBR_ANT_BIT    ; che stato ? ...
                je      pl44                    ; ... fibra diseccitata
                mov     fbr_stat,FBR_ANT_BIT    ; attesa fibra diseccitata
                jmp     pl1                     ; continua
        ENDIF

pl44:           mov     dx,SNS_INT              ; controlla barriera interna
                in      al,dx
                test    al,SNS_INT_BIT
                jnz     pl4                     ; barriera non interrotta
                mov     dx,SNS_CNT              ; controlla barriera centrale
                in      al,dx
                test    al,SNS_CNT_BIT
                jnz     pl4                     ; barriera non interrotta

                inc     ex                      ; controllo passi extra
                mov     ax,ex
                cmp     ax,20
        ;       cmp     ax,STEPS_ANT
                jb      pl3                     ; continua

                mov     al,'0'                  ; tutto ok
                jmp     plret

pl4:            mov     ax,steps
                cmp     ax,max_steps_cavt       ; controllo passi totali
                jb      pl2                     ; continua
                cmp     t,MAX_TNT               ; controlla tentativi
                mov     al,'A'
                jae     plret                   ; time-out
                call    place                   ; pinzata
                inc     t
                jmp     pl1                     ; riprova

plret:          push    ax                      ; salva esito
                mov     dx,ppen                 ; disabilita tappeti e pinza
                mov     al,ppen_bit
                call    setbit
                mov     dx,TEN
		mov	al,TEN_BIT
		call	setbit
		mov	di,OFFSET tten
		call	motoreoff
		pop	ax			; recupera esito
                ret
                ENDP

~
;******************************************************************************
;
;	gestione degli LM628
;
; input: dx = command-port
;
;******************************************************************************
				; LM628 user command set
RESET		EQU	00h		; reset LM628
PORT8		EQU	05h     	; select 8-bit output
PORT12		EQU	06h		; select 12-bit output
DFH		EQU	02h		; define home
SIP		EQU	03h     	; set index position
LPEI		EQU	1bh		; interrupt on error
LPES		EQU	1ah		; stop on eror
SBPA		EQU	20h		; set breakpoint, absolute
SBPR		EQU	21h		; set breakpoint, relative
MSKI		EQU	1ch		; mask interrupts
RSTI		EQU	1dh		; reset interrupts
LFIL		EQU	1eh		; load filter parameters
UDF		EQU	04h		; update filter
LTRJ		EQU	1fh		; load trajectory
STT		EQU	01h		; start motion
RDSIGS		EQU	0ch		; read signals register
RDIP		EQU	09h		; read index position
RDDP		EQU	08h		; read desired position
RDRP		EQU	0ah		; read real position
RDDV		EQU	07h		; read desired velocity
RDRV		EQU	0bh		; read real velocity
RDSUM		EQU	0dh		; read integration sum

ALL_INT		EQU	0000000001111110b	; mask for all interrupts

LALL_FIL	EQU	00001111b	; loading kp,ki,kd and il data
				; trajectory control word bit allocation
FWRD		EQU	0001000000000000b	; forward direction
VMODE		EQU	0000100000000000b	; velocity mode
STOP		EQU	0000010000000000b	; stop smoothly
BREAK		EQU	0000001000000000b	; stop abruptly
OFF		EQU	0000000100000000b	; turn off motor
LACC    	EQU	0000000000100000b	; loading acceleration data
LVEL		EQU	0000000000001000b	; loading velocity data
LPOS		EQU	0000000000000010b	; loading position data
				; status byte bit allocation
MT_OFF		EQU	10000000b	; motor off
BREAKPOINT	EQU	01000000b	; breakpoint reached [interrupt]
EX_POS_ERR      EQU     00100000b       ; excessive position error [interrupt]
WRAPAROUND	EQU	00010000b	; wraparound occurred [interrupt]
INDEX_PULSE	EQU	00001000b	; index pulse observed [interrupt]
TRJ_COMP	EQU	00000100b	; trajectory complete [interrupt]
CMD_ERROR	EQU	00000010b	; command error [interrupt]
BUSY_BIT	EQU	00000001b	; busy bit

; 	invia un comando all'LM628
;
; input: al = comando

wrcmd		PROC	NEAR
		push	ax
busy1:		in	al,dx		; attende che l'LM628 sia disponible
		test	al,BUSY_BIT
		jnz	busy1
		inc	dx   		; prima uno zero sulla data-port
		xor	al,al
		out	dx,al
		dec	dx              ; e poi il comando sulla command-port
		pop	ax
		out	dx,al
		ret
		ENDP

;	invia una word all'LM628
;
; input: ax = valore

wrword		PROC	NEAR
		push	ax
busy2:		in	al,dx		; attende che l'LM628 sia disponibile
		test	al,BUSY_BIT
		jnz	busy2
		inc	dx		; data-port
		pop	ax		; prima il byte pi— significativo
		xchg	al,ah
		out	dx,al
		xchg	al,ah           ; e poi quello meno significativo
		out	dx,al
		dec	dx   		; command-port
		ret
		ENDP

;	legge una word dall'LM628
;
; output: ax = valore

rdword		PROC	NEAR
		in	al,dx		; attende che l'LM628 sia disponibile
		test	al,BUSY_BIT
		jnz	rdword
		inc	dx		; data-port
		in	al,dx		; prima il byte pi— significativo
		mov	ah,al
		in	al,dx           ; e poi quello meno significativo
		dec	dx              ; command-port
		ret
		ENDP

;	resetta tutte le interruzzioni

rsti		PROC	NEAR
		mov	al,RSTI		; prima il comando di reset
		call	wrcmd
		mov	ax,NOT ALL_INT	; e poi la parola di controllo
		call	wrword
		ret
		ENDP

;	inizializza l'LM628
;
; input: ds:di+13 = puntatore ai parametri del filtro

DSI		EQU	[di+14]		; derivative sampling interval
KP		EQU	[di+15]		; proportional term
KI		EQU	[di+17]		; integration term
KD		EQU	[di+19]		; derivative term
IL		EQU	[di+21]		; integration limit

WAIT_RESET	EQU	0		; tempo attesa reset
MAX_PEI		EQU	7fffh		; max. errore di posizione senza stop

init628		PROC	NEAR
				; resetta l'LM628
		xor	ax,ax		; prima due zeri sulla data-port
		call	wrword
		mov	al,RESET	; poi il comando di reset
		call	wrcmd
		mov	cx,WAIT_RESET   ; e quindi attesa
		loop	$

		mov	al,PORT12	; seleziona l'output a 12 bits
		call	wrcmd
				; massimizza il massimo errore senza stop
		mov	al,LPEI		; prima il comando di caricamento
		call	wrcmd
		mov	ax,MAX_PEI	; e poi il valore effettivo
		call	wrword
				; inizializza i parametri del filtro
		mov	al,LFIL		; prima il comando di caricamento
		call	wrcmd
		mov	ah,DSI		; poi la parola di controllo con dsi
		mov	al,LALL_FIL
		call	wrword
		mov	ax,KP		; quindi il dato per kp
		call	wrword
		mov	ax,KI		; quello per ki
		call	wrword
		mov	ax,KD		; quello per kd
		call	wrword
		mov	ax,IL		; e quello per il
		call	wrword
		mov	al,UDF		; ed infine il comando
		call	wrcmd		; di aggiornamento effettivo
				; azzera i parametri della traiettoria
		mov	al,LTRJ		; prima il comando di caricamento
		call	wrcmd
		mov	ax,LACC OR LVEL OR LPOS	; poi la parola di controllo
		call	wrword
		mov	cx,6		; quindi i dati per acc=vel=pos=0
		xor	ax,ax
ini1:		call	wrword
		loop	ini1
		mov	al,DFH		; poi il comando per fissare l'origine
		call	wrcmd
		mov	al,STT          ; ed infine il comando
		call	wrcmd		; di aggiornamento effettivo
				; disabilita tutte le interruzzioni
		mov	al,MSKI         ; prima il comando di mascheramento
		call	wrcmd
		mov	ax,NOT ALL_INT	; e poi la parola di controllo
		call	wrword

		call	rsti		; resetta tutte le interruzzini

		ret
		ENDP

;******************************************************************************
;
;	gestione degli assi
;
; input: ds:di = puntatore ai parametri dell'asse
;
;******************************************************************************

CMD_PORT        EQU     [di+0]          ; command-port
ENABLE		EQU	[di+2]		; abilitazione asse
ENABLE_BIT	EQU	[di+4]
VER_AB          EQU     [di+5]          ; verifica abilitazione
VER_AB_BIT      EQU     [di+7]
SNS_1		EQU	[di+8]		; sensore 1
SNS_1_BIT	EQU	[di+10]
SNS_2		EQU	[di+11]		; sensore 2
SNS_2_BIT	EQU	[di+13]

FILTER		EQU	[di+14]		; parametri filtro
ACC_LOW		EQU	[di+23]		; accelerazione
ACC_HIGH	EQU	[di+25]
SSLOW_LOW       EQU     [di+27]         ; velocit… bassissima
SSLOW_HIGH      EQU     [di+29]
SLOW_LOW        EQU     [di+31]         ; bassa velocit…
SLOW_HIGH       EQU     [di+33]
FAST_LOW        EQU     [di+35]         ; alta velocit…
FAST_HIGH       EQU     [di+37]
POS_LOW         EQU     [di+39]         ; posizione
POS_HIGH        EQU     [di+41]
WAIT_1          EQU     [di+43]         ; attesa raggiunta 1 per origine

WAIT_ARR	EQU	12		; tempo attesa arresto effettivo asse

				; parametri asse x
xport		DW	0300h		; command-port
xenable		DW	0310h		; abilitazione
xenable_bit	DB	10000000b
xab             DW      0316h           ; verifica abilitazione
xab_bit         DB      00000010b
xsns_1          DW      031Ah           ; sensore 1
xsns_1_bit      DB      00100000b
xsns_2          DW      031Ah           ; sensore 2
xsns_2_bit      DB      00010000b

xdsi		DB	0  		; parametri filtro
xkp             DW	8
xki             DW	5
xkd             DW	20
xil             DW	0

xacc		DD	700		; accelerazione
xsslow		DD      1000		; bassissima velocit…
xslow		DD	20000		; bassa velocit…
xfast           DD      150000          ; alta velocit…
xpos		DW	0,0		; posizione
xwait_1         DW      546             ; attesa raggiunta 1 per origine

				; parametri asse z
zport		DW	0304h		; command-port
zenable		DW	0310h		; abilitazione
zenable_bit     DB      01000000b
zab             DW      0316h           ; verifica abilitazione
zab_bit         DB      00000100b
zsns_1          DW      031Ah           ; sensore 1
zsns_1_bit      DB      00000100b
zsns_2          DW      031Ah           ; sensore 2
zsns_2_bit      DB      00000010b

zdsi		DB	0  		; parametri filtro
zkp             DW	8
zki             DW	5
zkd             DW	20
zil             DW	0

zacc		DD	120		; accelerazione
zsslow		DD      3000		; bassissima velocit…
zslow		DD	90000		; bassa velocit…
zfast		DD	2750000		; alta velocit…
zpos		DW	0,0		; posizione
zwait_1         DW      728             ; attesa raggiunta 1 per origine

;	riporta lo stato dell'asse dedotto dalla lettura dei sensori
;
; output: ah = 00000XX0b
;                   ³³
;                   ³ÀÄÄÄ not stato sensore 1
;                   ÀÄÄÄÄ not stato sensore 2

assestatus     	PROC	NEAR
		xor	ah,ah

                mov     dx,SNS_1        ; controlla sensore 1
		in	al,dx
		test	al,SNS_1_BIT
                jnz     as1             ; sensore rilasciato
		or	ah,00000010b	; SENSORE PREMUTO !!!

as1:            mov     dx,SNS_2        ; controlla sensore 2
		in	al,dx
		test	al,SNS_2_BIT
                jnz     as2             ; sensore rilasciato
		or	ah,00000100b	; SENSORE PREMUTO !!!

as2:            ret
		ENDP

;	sposta l'asse in modo posizione

position	PROC	NEAR
		mov	dx,CMD_PORT	; command-port
		mov	al,LTRJ		; carica la traiettoria
		call	wrcmd
		mov	ax,LVEL OR LPOS
		call	wrword
		mov	ax,FAST_HIGH		; velocit…
		call	wrword
		mov	ax,FAST_LOW
		call	wrword
		mov	ax,POS_HIGH		; posizione
		call	wrword
		mov	ax,POS_LOW
		call	wrword
		call	rsti		; resetta le interruzzioni
		mov	al,STT		; inizia lo spostamento
		call	wrcmd
		ret
		ENDP

;	sposta l'asse in modo velocit…

forward		PROC	NEAR		; direzione indietro/basso
		mov	ah,(VMODE OR FWRD) SHR 8
		jmp	SHORT velocity

backward:	mov	ah,VMODE SHR 8	; direzione avanti/alto

velocity:       mov	dx,CMD_PORT	; command-port
		mov	al,LTRJ		; carica la traiettoria
		call	wrcmd
		mov	al,LVEL
		call	wrword
		mov	ax,SLOW_HIGH
		call	wrword
		mov	ax,SLOW_LOW
		call	wrword
		call	rsti		; resetta le interruzzioni
		mov	al,STT          ; inizia lo spostamento
		call	wrcmd
		ret
		ENDP

; 	attende l'arresto effettivo dell'asse

waitarr		PROC	NEAR
		mov	bx,WAIT_ARR	; attesa arresto
wa1:		xor	cx,cx
		loop	$
		dec	bx
		jnz	wa1
		ret
		ENDP

;	arresta l'asse

stop		PROC	NEAR		; deccelerazione programmata
		mov	ah,STOP SHR 8
		jmp	SHORT arresto

break:          mov	ah,BREAK SHR 8	; massima deccelerazione
		jmp	SHORT arresto

off:		mov	ah,OFF SHR 8	; blocco immediato

arresto:        mov	dx,CMD_PORT	; command-port
		mov	al,LTRJ		; carica la traiettoria
		call	wrcmd
		xor	al,al
		call	wrword
		call	rsti		; resetta le interruzzioni
		mov	al,STT		; inizia arresto
		call	wrcmd
arr1:		in	al,dx     	; attende arresto
		test	al,TRJ_COMP
		jz	arr1
		call	waitarr		; attende arresto effettivo
		ret
		ENDP

;       resetta l'asse

reset           PROC    NEAR
                in      al,61h          ; beep
                mov     cx,500
ll11:           xor     al,00000010b
                out     61h,al
                push    cx
                mov     cx,200
                loop    $
                pop     cx
                loop    ll11

		mov	dx,CMD_PORT	; command-port
		call	init628		; inizializza l'LM628
		mov	al,LTRJ		; fissa l'accelerazione
		call	wrcmd
		mov	ax,LACC
		call	wrword
		mov	ax,ACC_HIGH
		call	wrword
		mov	ax,ACC_LOW
		call	wrword
		mov     ax,STT
		call	wrcmd
		call	waitarr		; attende arresto asse
		call	waitarr
                call    waitarr
                ret
                ENDP

;	sposta l'asse dai sensori 1 e 2
;
; output: carry-flag = reset se tutto ha funzionato a dovere
;	  carry-flag = set   se l'asse Š bloccato o si Š verificato un errore

ttt             DW      ?
tnt_nosns       DW      ?

nosns		PROC	NEAR
                call    assestatus      ; legge stato micro

        ; controlla micro 1

                test    ah,00000010b    ; controlla micro 1
                jz      ns4             ; micro 1 rilasciato

        ; sposta l'asse dal micro 1

                mov     tnt_nosns,0     ; # tentativi fatti

ns1:            call    forward         ; inizia spostamento
                mov     ax,time         ; registra istante attuale
                mov     ttt,ax

ns2:            call    assestatus      ; legge stato micro

                test    ah,00000100b    ; controlla micro 2
                jnz     nsoff           ; MICRO 2 PREMUTO !!!

                mov     ax,time         ; controlla tempo trascorso
                sub     ax,ttt
                jnc     ns3
                neg     ax              ; evita l'overflow del timer
ns3:            cmp     ax,54
                jb      ns2             ; tempo inferiore a 3 sec.

                call    stop            ; arresta l'asse

                call    assestatus      ; legge stato micro

                test    ah,00000100b    ; controlla micro 2
                jnz     nsoff           ; MICRO 2 PREMUTO !!!

                test    ah,00000010b    ; controlla micro 1
                jz      nsok            ; micro 1 rilasciato

                inc     tnt_nosns       ; controlla tentativi
                cmp     tnt_nosns,3
                jae     nsoff           ; troppi: ERRORE !!!

                call    reset           ; resetta l'asse
                jmp     ns1             ; riprova

        ; controlla micro 2

ns4:            test    ah,00000100b    ; controlla micro 2
                jz      nsok            ; micro 2 rilasciato

        ; sposta l'asse dal micro 2

                mov     tnt_nosns,0     ; # tentativi fatti

ns5:            call    backward        ; inizia spostamento
                mov     ax,time         ; registra istante attuale
                mov     ttt,ax

ns6:            call    assestatus      ; legge stato micro

                test    ah,00000010b    ; controlla micro 1
                jnz     nsoff           ; MICRO 1 PREMUTO !!!

                mov     ax,time         ; controlla tempo trascorso
                sub     ax,ttt
                jnc     ns7
                neg     ax              ; evita l'overflow del timer
ns7:            cmp     ax,54
                jb      ns6             ; tempo inferiore a 3 sec.

                call    stop            ; arresta l'asse

                call    assestatus      ; legge stato micro

                test    ah,00000010b    ; controlla micro 1
                jnz     nsoff           ; MICRO 1 PREMUTO !!!

                test    ah,00000100b    ; controlla micro 2
                jz      nsok            ; micro 2 rilasciato

                inc     tnt_nosns       ; controlla tentativi
                cmp     tnt_nosns,3
                jae     nsoff           ; troppi: ERRORE !!!

                call    reset           ; resetta l'asse
                jmp     ns5             ; riprova

nsoff:          mov     dx,ENABLE       ; disabilita l'asse
		mov	al,ENABLE_BIT
		call	setbit
		call	off		; blocca l'asse
		stc	            	; ERRORE !!!
		ret

nsok:		clc			; tutto ok
                ret
		ENDP

;       inizializza l'asse
;
; output: carry-flag = reset se tutto ha funzionato a dovere
;	  carry-flag = set   se si Š verificato un errore

tt              DW      ?
tnt_init        DW      ?

asseinit	PROC	NEAR
		mov	dx,ENABLE	; abilita l'asse
		mov	al,ENABLE_BIT
		call	resetbit

                call    reset           ; resetta l'asse

                call    nosns           ; sposta l'asse dai sensori 1 e 2
                jc      aierr           ; ERRORE !!!

        ; attende mcr_1 = 1

                mov     tnt_init,0      ; # tentativi

aini1:          call    backward        ; inizia spostamento
                mov     ax,time         ; registra istante attuale
                mov     tt,ax

aini2:          call    assestatus      ; legge stato micro
                test    ah,00000100b    ; controlla micro 2
                jnz     aierr           ; MICRO 2 PREMUTO !!!
                test    ah,00000010b    ; controlla micro 1
                jnz     aini4           ; micro 1 premuto

                mov     ax,time         ; controlla tempo trascorso
                sub     ax,tt
                jnc     aini3
                neg     ax              ; evita l'overflow del timer
aini3:          cmp     ax,WAIT_1
                jb      aini2

                call    stop            ; arresta l'asse

                call    assestatus      ; legge stato micro
                test    ah,00000100b    ; controlla micro 2
                jnz     aierr           ; MICRO 2 PREMUTO !!!

                inc     tnt_init        ; controlla tentativi
                cmp     tnt_init,3
                jae     aierr           ; troppi: ERRORE !!!

                call    reset           ; resetta l'asse
                jmp     aini1           ; riprova

aierr:          mov     dx,ENABLE       ; toglie l'abilitazione
		mov	al,ENABLE_BIT
		call	setbit
                call    off             ; blocca l'asse
                stc                     ; ERRORE !!!
		ret

        ; attende mcr_1 = 0

aini4:          call    break           ; arresta l'asse

                push    SLOW_HIGH       ; salva bassa velocit…
		push	SLOW_LOW
                mov     ax,SSLOW_HIGH   ; imposta bassissima velocit…
		mov	SLOW_HIGH,ax
		mov	ax,SSLOW_LOW
		mov	SLOW_LOW,ax

                mov     tnt_init,0      ; # tentativi

aini6:          call    forward         ; inizia spostamento
                mov     ax,time         ; registra istante attuale
                mov     tt,ax

aini7:          call    assestatus      ; legge stato micro
                test    ah,00000100b    ; controlla micro 2
                jnz     _aierr          ; MICRO 2 PREMUTO !!!
                test    ah,00000010b    ; controlla micro 1
                jnz     aini8           ; micro 1 premuto

                mov     cx,WAIT_SNS     ; attende stabilit… segnale
                loop    $

                call    assestatus      ; legge stato micro
                test    ah,00000100b    ; controlla micro 2
                jnz     _aierr          ; MICRO 2 PREMUTO !!!
                test    ah,00000010b    ; controlla micro 1
                jz      aini10          ; micro 1 rilasciato

aini8:          mov     ax,time         ; controlla tempo trascorso
                sub     ax,tt
                jnc     aini9
                neg     ax              ; evita l'overflow del timer
aini9:          cmp     ax,182
                jb      aini7           ; tempo inferiore a 10 sec.

                call    stop            ; arresta l'asse

                call    assestatus      ; legge stato micro
                test    ah,00000100b    ; controlla micro 2
                jnz     _aierr          ; MICRO 2 PREMUTO !!!

                inc     tnt_init        ; controlla tentativi
                cmp     tnt_init,3
                jae     _aierr          ; troppi: ERRORE !!!

                call    reset           ; resetta l'asse
                jmp     aini6           ; riprova

aini10:         mov     dx,CMD_PORT     ; fissa l'origine
		mov	al,DFH
		call	wrcmd

                pop     SLOW_LOW        ; recupera bassa velocit…
		pop	SLOW_HIGH

                call    stop            ; arresta l'asse

                clc                     ; tutto ok
		ret

_aierr:         pop     SLOW_LOW        ; recupera bassa velocit…
		pop	SLOW_HIGH
                jmp     aierr
		ENDP

;       trova la distanza fra i due micro fine-corsa dell'asse
;
; output: DX:AX = valore trovato (0 in caso di errore)

assedist        PROC    NEAR
                call    nosns           ; sposta l'asse dai sensori 1 e 2
                jc      aderr           ; ERRORE !!!

        ; attende mcr_2 = 1

                mov     tnt_init,0      ; # tentativi

adis1:          call    forward         ; inizia spostamento
                mov     ax,time         ; registra istante attuale
                mov     tt,ax

adis2:          call    assestatus      ; legge stato micro
                test    ah,00000010b    ; controlla micro 1
                jnz     aderr           ; MICRO 1 PREMUTO !!!
                test    ah,00000100b    ; controlla micro 2
                jnz     adis4           ; micro 2 premuto

                mov     ax,time         ; controlla tempo trascorso
                sub     ax,tt
                jnc     adis3
                neg     ax              ; evita l'overflow del timer
adis3:          cmp     ax,WAIT_1
                jb      adis2

                call    stop            ; arresta l'asse

                call    assestatus      ; legge stato micro
                test    ah,00000010b    ; controlla micro 1
                jnz     aderr           ; MICRO 1 PREMUTO !!!

                inc     tnt_init        ; controlla tentativi
                cmp     tnt_init,3
                jae     aderr           ; troppi: ERRORE !!!

                jmp     adis1           ; riprova

aderr:          mov     dx,ENABLE       ; toglie l'abilitazione
		mov	al,ENABLE_BIT
		call	setbit
                call    off             ; blocca l'asse
                xor     ax,ax           ; ERRORE !!!
                xor     dx,dx
		ret

        ; attende mcr_2 = 0

adis4:          call    break           ; arresta l'asse

                push    SLOW_HIGH       ; salva bassa velocit…
		push	SLOW_LOW
                mov     ax,SSLOW_HIGH   ; imposta bassissima velocit…
		mov	SLOW_HIGH,ax
		mov	ax,SSLOW_LOW
		mov	SLOW_LOW,ax

                mov     tnt_init,0      ; # tentativi

adis6:          call    backward        ; inizia spostamento
                mov     ax,time         ; registra istante attuale
                mov     tt,ax

adis7:          call    assestatus      ; legge stato micro
                test    ah,00000010b    ; controlla micro 1
                jnz     _aderr          ; MICRO 1 PREMUTO !!!
                test    ah,00000100b    ; controlla micro 2
                jnz     adis8           ; micro 2 premuto

                mov     cx,WAIT_SNS     ; attende stabilit… segnale
                loop    $

                call    assestatus      ; legge stato micro
                test    ah,00000010b    ; controlla micro 1
                jnz     _aderr          ; MICRO 1 PREMUTO !!!
                test    ah,00000100b    ; controlla micro 2
                jz      adis10          ; micro 2 rilasciato

adis8:          mov     ax,time         ; controlla tempo trascorso
                sub     ax,tt
                jnc     adis9
                neg     ax              ; evita l'overflow del timer
adis9:          cmp     ax,182
                jb      adis7           ; tempo inferiore a 10 sec.

                call    stop            ; arresta l'asse

                call    assestatus      ; legge stato micro
                test    ah,00000010b    ; controlla micro 1
                jnz     _aderr          ; MICRO 1 PREMUTO !!!

                inc     tnt_init        ; controlla tentativi
                cmp     tnt_init,3
                jae     _aderr          ; troppi: ERRORE !!!

                jmp     adis6           ; riprova

adis10:         call    stop            ; arresta l'asse
                pop     SLOW_LOW        ; recupera bassa velocit…
		pop	SLOW_HIGH

                mov     dx,CMD_PORT     ; legge la posizione attuale
		mov	al,RDRP
		call	wrcmd
		call	rdword
		push	ax
		call	rdword
                pop     dx              ; dx = MSW , ax = LSW
                ret                     ; tutto ok

_aderr:         pop     SLOW_LOW        ; recupera bassa velocit…
		pop	SLOW_HIGH
                jmp     aderr
		ENDP

;       inizializza l'asse X
;
;   out: AL = esito ('0' -> ok, 'X' -> errore)

__vbinitx       PROC    NEAR
                mov     di,OFFSET xport ; inizializza
		call	asseinit
                mov     al,'X'          ; ERRORE !!!
                jc      ixret
                mov     al,'0'          ; ok
ixret:          ret
                ENDP

;       inizializza l'asse Z
;
;   out: AL = esito ('0' -> ok, 'Z' -> errore)

__vbinitz       PROC    NEAR
                mov     di,OFFSET zport ; inizializza
		call	asseinit
                mov     al,'Z'          ; ERRORE !!!
                jc      izret
                mov     al,'0'          ; ok
izret:          ret
                ENDP

;       trova la distanza fra i due micro fine-corsa dell'asse X
;
;   out: DX:AX = valore trovato (0 in caso di errore)

__vbdisx        PROC    NEAR
                mov     di,OFFSET xport ; imposta asse x
                call    assedist        ; trova distanza
                ret
                ENDP

;       trova la distanza fra i due micro fine-corsa dell'asse Z
;
;   out: DX:AX = valore trovato (0 in caso di errore)

__vbdisz        PROC    NEAR
                mov     di,OFFSET zport ; imposta asse z
                call    assedist        ; trova distanza
                ret
                ENDP

;*****************************************************************************
;
;	gestione del posizionamento degli assi
;
; input:  DATI.TXT = file con la posizione da raggiungere
;
; output: AL = '0' se tutto ok
;         AL = 'I' se pinza in stato errato
;         AL = 'F' se errore nel file
;         AL = 'P' se errore nello spostamento
;
;******************************************************************************

posfile         DB      'DATI.TXT',0    ; file con la posizione

time            DW      ?       ; contatori tempo
old             DW      ?
old1            DW      ?

tnt_goto        DW      ?

__vbgotoxz      PROC    NEAR

        ; controllo stato pinza

                call    statopinza
                jnc     go1             ; pinza ok
                mov     al,'I'          ; PINZA IN STATO ERRATO !!!
                ret

        ; lettura posizione da raggiungere

go1:            mov     ax,3d00h        ; apertura file DATI.TXT
		mov	dx,OFFSET posfile
		int	21h
                jc      fileerrret      ; APERTURA FALLITA !!!

                mov     bx,ax           ; lettura posizione x
		mov	cx,4
		mov	dx,OFFSET xpos
		mov	ah,3fh
		int	21h
                jc      fileerr         ; LETTURA FALLITA !!!
		cmp	ax,4
                jne     fileerr         ; LETTURA ERRATA !!!

                mov     dx,OFFSET zpos  ; lettura posizione z
                mov     ah,3fh
		int	21h
                jc      fileerr         ; LETTURA FALLITA !!!
		cmp	ax,4
                jne     fileerr         ; LETTURA ERRATA !!!

                mov     ah,3eh          ; chiusura file
		int	21h
                jnc     go2             ; chiusura ok

fileerr:        mov     ah,3eh          ; chiusura file
		int	21h
fileerrret:     mov     al,'F'          ; ERRORE NEL FILE !!!
                ret

        ; inizia traiettoria

go2:            mov     di,OFFSET ppen  ; attiva motori pinza
		call	motoreon
		mov	di,OFFSET tten
		call	motoreon

                mov     tnt_goto,0      ; # tentativi posizonamento

_go2:           mov     di,OFFSET xport ; inizia spostamento
		call	position
		mov	di,OFFSET zport
		call	position

                mov     time,0          ; tempo trascorso
                mov     old,0           ; istante ultima lettura posizione

        ; attende completamento traiettoria e controlla errori

gonext:         mov     ax,time         ; istante ultima constatazione assi
                mov     old1,ax         ;   non in quota

gonext1:        cmp     time,182        ; controlla tempo trascorso con 10 s.
                jb      _gonext1

                inc     tnt_goto        ; controlla tentativi fatti
                cmp     tnt_goto,3
                jae     goerr           ; TIME-OUT: 3 tentativi fatti !!!

                in      al,61h          ; beep
                mov     cx,500
ll22:           xor     al,00000010b
                out     61h,al
                push    cx
                mov     cx,200
                loop    $
                pop     cx
                loop    ll22

                jmp     _go2            ; riprova

_gonext1:  ;    mov     di,OFFSET xport ; controlla fine-corsa x
           ;    call    assestatus
           ;    test    ah,00000110b
           ;    jz      go3             ; fine-corsa rilasciati

           ;    mov     cx,8000h        ; attende e ricontrolla fine-corsa x
           ;    loop    $
           ;    call    assestatus
           ;    test    ah,00000110b
           ;    jnz     goerr           ; FINE-CORSA PREMUTI !!!

go3:       ;    mov     di,OFFSET zport ; controlla fine-corsa z
           ;    call    assestatus
           ;    test    ah,00000110b
           ;    jz      go4             ; fine-corsa rilasciati

           ;    mov     cx,8000h        ; attende e ricontrolla fine-corsa z
           ;    loop    $
           ;    call    assestatus
           ;    test    ah,00000110b
           ;    jnz     goerr           ; FINE-CORSA PREMUTI !!!

go4:       ;    mov     dx,xport        ; controlla status byte LM628 x
           ;    in      al,dx
           ;    test    al,EX_POS_ERR
           ;    jnz     goerr           ; EXCESSIVE POSITION ERROR !!!

           ;    mov     dx,zport        ; controlla status byte LM628 z
           ;    in      al,dx
           ;    test    al,EX_POS_ERR
           ;    jnz     goerr           ; EXCESSIVE POSITION ERROE !!!

                jmp     SHORT go5

goerr:          mov     dx,xenable      ; disabilita l'asse x
		mov	al,xenable_bit
		call    setbit
                mov     dx,zenable      ; disabilita l'asse z
		mov	al,zenable_bit
		call	setbit

                mov     di,OFFSET xport ; blocca l'asse x
		call	off
                mov     di,OFFSET zport ; blocca l'asse z
		call	off

		mov	al,'P'		; POSIZIONE NON RAGGIUNTA !!!
                jmp     goret

go5:            mov     dx,xport        ; controlla status byte LM628 x
		in	al,dx
		test	al,TRJ_COMP
                jz      gonextr         ; asse x in movimento

                mov     di,zport        ; controlla status byte LM628 z
		in	al,dx
		test	al,TRJ_COMP
                jz      gonextr         ; asse z in movimento

                mov     ax,time         ; intervalla le operazioni succesive
                sub     ax,old          ;   di 0.1 secondi
                cmp     ax,2
                jb      gonext1r

                mov     ax,time         ; istante ultima lettura posizione
                mov     old,ax

                mov     dx,xport        ; legge posizione x attuale
		mov	al,RDRP
		call	wrcmd
		call	rdword
		push	ax
		call	rdword
                pop     dx              ; dx = MSW , ax = LSW

		add	ax,100		; somma epsilon
		adc	dx,0

		cmp	dx,xpos[2]	; controlla limite inferiore
                jl      gonextr         ; quota non raggiunta
                jg      go6
		cmp	ax,xpos[0]
                jbe     gonextr         ; quota non raggiunta

go6:            add     ax,-200         ; sottrae epsilon
		adc	dx,-1

		cmp	dx,xpos[2]	; controlla limite superiore
                jg      gonextr         ; quota non raggiunta
                jl      go7             ; quota x raggiunta
		cmp	ax,xpos[0]
                jb      go7             ; quota x raggiunta

gonextr:        jmp     gonext
gonext1r:       jmp     gonext1

go7:            mov     dx,zport        ; legge la posizione z attuale
		mov	al,RDRP
		call	wrcmd
		call	rdword
		push	ax
		call	rdword
                pop     dx              ; dx = MSW , ax = LSW

		add	ax,400		; somma epsilon
		adc	dx,0

		cmp	dx,zpos[2]	; controlla limite inferiore
                jl      gonextr         ; quota non raggiunta
                jg      go8
		cmp	ax,zpos[0]
                jbe     gonextr         ; quota non raggiunta

go8:            add     ax,-800         ; sottrae epsilon
		adc	dx,-1

		cmp	dx,zpos[2]	; controlla limte superiore
                jg      gonextr         ; quota non raggiunta
                jl      go9             ; quota z raggiunta
		cmp	ax,zpos[0]
                jae     gonextr         ; quota non raggiunta

go9:            mov     ax,time         ; controllo tempo assi in quota
                sub     ax,old1
                cmp     ax,9
                jb      gonext1r        ; tempo inferiore a 0.5 secondi

                mov     al,'0'          ; ok

goret:          push    ax              ; salva esito
		mov	di,OFFSET ppen	; disattiva motori pinza
		call	motoreoff
		mov	di,OFFSET tten
		call	motoreoff
                pop     ax              ; recupera esito
                ret
                ENDP

;******************************************************************************
;
;	inizializzazione VIDEOBANK
;
; output: param = '0' se tutto ha funzionato a dovere
;	  param = 'A' se si Š verificato un errore inizializzando la porta
;	  param = 'B' se si Š verificato un errore inizializzando la pinza
;         param = 'C' se il tappeto Š in stato errato
;	  param = 'X' se si Š verificato un errore inizializzando l'asse x
;         param = 'Z' se si Š verificato un errore inizializzando l'asse z
;
;******************************************************************************

__vbinit        PROC    NEAR
                mov     dx,0310h        ; setta tutte le porta di output
                mov     al,11111111b
                call    setbit
                mov     dx,0312h
                mov     al,11111101b    ; (lo Z80 non deve essere resettato)
                call    setbit
                mov     dx,0314h
                mov     al,11111111b
                call    setbit
                mov     dx,0318h
                mov     al,11111111b
                call    setbit
                mov     dx,031Ch
                mov     al,11111111b
                call    setbit

                call    tappstatus      ; controlla stato tappeto
                cmp     ah,00000111b
                je      __i1
                mov     al,'C'          ; TAPPETO NON OK !!!
                ret

__i1:           call    __vbdown        ; chiude porta
                cmp     al,'0'
                je      __i2
                mov     al,'A'          ; PORTA NON OK !!!
                ret

					; inizializza gruppo pinza

__i2:
        IF BARGP EQ 0                           ; se non ci sono le barriere
                mov     di,OFFSET tten          ; controlla presenza cassetta
                mov     tout0,FBR_ANT
                mov     tout0_bit,FBR_ANT_BIT
                mov     si,OFFSET tout0
                call    motore1
                jnc     pnzerr                  ; cassetta presente
        ENDIF

                mov     di,OFFSET ppen          ; preme il micro posteriore
                mov     si,OFFSET mcr_ant
                mov     mcr_ant_stat,0          ; prova 1 volta
                call    motore0
                mov     mcr_ant_stat,MCR_POS_BIT
                jnc     _i1                     ; ok
                mov     mcr_ant_stat,0          ; prova 1 volta
                call    motore0
                mov     mcr_ant_stat,MCR_POS_BIT
                jnc     _i1                     ; ok
                mov     mcr_ant_stat,0          ; prova 1 volta
                call    motore0
                mov     mcr_ant_stat,MCR_POS_BIT
                jnc     _i1                     ; ok

pnzerr:         mov     al,'B'                  ; PINZA NON OK !!!
                ret

_i1:            call    statopinza              ; completa inizializzazione
                jc      pnzerr                  ; PINZA NON OK !!!
        IF BARGP EQ 1
                jz      pnzerr                  ; PINZA NON OK !!!
        ENDIF
                mov     dx,MCR_CNT              ; controlla micro centrale
                in      al,dx
                test    al,MCR_CNT_BIT
                jnz     pnzerr                  ; micro rilasciato
                mov     dx,FBR_ANT              ; controlla fibra anteriore
                in      al,dx
                test    al,FBR_ANT_BIT
                jz      pnzerr                  ; fibra eccitata
                mov     dx,FBR_POS              ; controlla fibra posteriore
                in      al,dx
                test    al,FBR_POS_BIT
                jz      pnzerr                  ; fibra eccitata

                mov     di,OFFSET ppen  ; abilita trasporto
                call    motoreon
                mov     di,OFFSET tten  ; disattiva tappeto
		call	motoreoff

                mov     di,OFFSET zport ; inizializza asse z
		call	asseinit
		mov	al,'Z'
                jc      initret         ; ASSE Z NON OK !!!

                mov     di,OFFSET xport ; inizializza asse x
		call	asseinit
		mov	al,'X'
                jc      initret         ; ASSE X NON OK !!!

                mov     di,OFFSET ppen  ; disattiva trasporto
		call	motoreoff

                mov     al,'0'          ; tutto ok
initret:        ret
		ENDP

;******************************************************************************
;
;	VIDEOBANK in errore
;
; output: param = '0' se tutto ha funzionato a dovere
;	  param = 'A' se la porta non si Š chiusa
;
;******************************************************************************

__vbleave       PROC    NEAR
                mov     dx,0310h        ; setta tutte le porta di output
                mov     al,11111111b
                call    setbit
                mov     dx,0312h
                mov     al,11111101b    ; (lo Z80 non deve essere resettato)
                call    setbit
                mov     dx,0314h
                mov     al,11111111b
                call    setbit
                mov     dx,0318h
                mov     al,11111111b
                call    setbit
                mov     dx,031Ch
                mov     al,11111111b
                call    setbit

                mov     di,OFFSET xport ; blocca gli assi
		call	off
		mov	di,OFFSET zport
		call	off

                call    __vbdown        ; chiude la porta
                cmp     al,'0'
                je      leaveret        ; porta chiusa
                mov     al,'A'          ; porta non chiusa
leaveret:       ret
		ENDP

;       carica i parametri dal file C:\VBL\PARAM.TXT

param           DB      'C:\VBL\PARAM.TXT',0    ; file con i parametri

__lparam        PROC    NEAR
                mov     ax,3d00h        ; apre il file in lettura
                mov     dx,OFFSET param
                int     21h

                mov     bx,ax
                mov     cx,2

                mov     ah,3fh
                mov     dx,OFFSET VEL_REG
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET STEPS_INT
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET pstart_vel
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_up
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_down
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET ppstart_vel
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET ttstart_vel
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET vicino_ant
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_ravt
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_ind
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_aind
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_cavt
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET vicino_pos
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_rind
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_avt
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_pavt
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET steps_sns_cind
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET STEPS_ANT
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET STEPST
                int     21h

                mov     ah,3fh
                mov     dx,OFFSET STEPSP
                int     21h

                mov     ah,3eh  ; chiude il file
                int     21h

                mov     ax,ppstart_vel
                mov     ppvel,ax
                mov     ax,ttstart_vel
                mov     ttvel,ax
                ret
                ENDP

;******************************************************************************
;
;       gestione del lettore di banconote
;
; output: AL = 'G' -> lettore guasto
;              'T' -> time-out attendendo una banconota
;              '1' -> tasto ESC premuto
;              '2' -> tasto F9 premuto
;              'A' -> banconota da L. 10000
;              'B' -> banconota da L. 5000
;              'C' -> banconota da L. 50000
;
;******************************************************************************

OOO             EQU     0314h
OOO_BIT         EQU     01000000b
LBUSY           EQU     0314h
LBUSY_BIT       EQU     00100000b
DATA_V          EQU     0314h
DATA_V_BIT      EQU     00000010b
DATA_1          EQU     0314h
DATA_1_BIT      EQU     00000100b
DATA_2          EQU     0314h
DATA_2_BIT      EQU     00001000b
DATA_3          EQU     0314h
DATA_3_BIT      EQU     00010000b

BLOCK           EQU     0314h
BLOCK_BIT       EQU     00000010b
AUX1            EQU     0318h
AUX1_BIT        EQU     10000000b
AUX2            EQU     0318h
AUX2_BIT        EQU     00000010b

__vbrdban       PROC    NEAR
                mov     dx,OOO          ; controlla stato lettore
                in      al,dx
                test    al,OOO_BIT
                jnz     ban0            ; lettore funzionante
                mov     al,'G'
                jmp     banret          ; lettore guasto

ban0:           mov     dx,BLOCK        ; abilita ingresso banconote
                mov     al,BLOCK_BIT
                call    resetbit

                mov     time,0          ; registra istante attuale

ban1:           mov     dx,DATA_V       ; banconota presente ?
                in      al,dx
                test    al,DATA_V_BIT
                jnz     ban2            ; no: attendi

                mov     cx,8000h        ; si: attendi un po' e ...
                loop    $
                in      al,dx           ; verifica banconota presente
                test    al,DATA_V_BIT
                jnz     ban2            ; no: attendi

                mov     dx,DATA_2       ; controlla se banconota da L. 5000
                in      al,dx
                test    al,DATA_2_BIT
                mov     al,'B'
                jz      ban4            ; L. 5000
                mov     dx,DATA_3       ; controlla se banconota da L. 10000
                in      al,dx
                test    al,DATA_3_BIT
                mov     al,'A'
                jz      ban4            ; L. 10000
                mov     dx,DATA_1       ; controlla se banconota da L. 50000
                in      al,dx
                test    al,DATA_1_BIT
                mov     al,'C'
                jz      ban4            ; L. 50000
                mov     al,'G'          ; lettore guasto
                jmp     ban4

ban2:           mov     dx,LBUSY        ; controlla busy
                in      al,dx
                test    al,LBUSY_BIT
                jz      ban1            ; lettore occupato

                mov     ah,01h          ; controlla buffer tastiera
		int	16h
                jz      ban3            ; buffer vuoto
                xor     ah,ah           ; legge tasto
		int	16h
                mov     dx,ax
                cmp     dx,ESC_KEY
		mov	al,'1'
                je      ban4            ; tasto ESC
		cmp	dx,F9_KEY
		mov	al,'2'
                je      ban4            ; tasto F9

ban3:           cmp     time,182        ; controlla tempo trascorso
                jb      ban1            ; continua
                mov     al,'T'          ; time-out

ban4:           push    ax              ; salva esito

                mov     dx,BLOCK        ; disabilita ingresso banconote
                mov     al,BLOCK_BIT
                call    setbit

                mov     dx,LBUSY        ; attesa arresto motore
ban5:           in      al,dx
                test    al,LBUSY_BIT
                jz      ban5            ; motore in movimento

                pop     ax              ; recupera esito
banret:         ret
                ENDP

;       riporta in AL lo stato del tunnel
;
; out: bit0 = stato barriera esterna
;      bit1 = stato barriere interna e centrale (1->non interrotte,0->almeno 1 interrotta)
;      bit2 = stato barriera anteriore
;      bit3 = stato barriera posteriore

__vbstatus      PROC    NEAR
                mov     ah,1111b        ; imposta barriere non interrotte

                mov     dx,SNS_EST      ; controlla barriere esterna
                in      al,dx
                test    al,SNS_EST_BIT
                jnz     __vbst1         ; barriera non interrotta
                and     ah,1110b        ; barriera interrotta

__vbst1:        mov     dx,SNS_CNT      ; controlla barriere centrale
                in      al,dx
                test    al,SNS_CNT_BIT
                jnz     __vbst2         ; barriera non interrotta
                and     ah,1101b        ; barriera interrotta

__vbst2:        mov     dx,SNS_INT      ; controlla barriere interna
                in      al,dx
                test    al,SNS_INT_BIT
                jnz     __vbst3         ; barriera non interrotta
                and     ah,1101b        ; barriera interrotta

__vbst3:        mov     dx,BAR_ANT      ; controlla barriere anteriore
                in      al,dx
                test    al,BAR_ANT_BIT
                jnz     __vbst4         ; barriera non interrotta
                and     ah,1011b        ; barriera interrotta

__vbst4:        mov     dx,BAR_POS      ; controlla barriere posteriore
                in      al,dx
                test    al,BAR_POS_BIT
                jnz     __vbst5         ; barriera non interrotta
                and     ah,0111b        ; barriera interrotta

__vbst5:        mov     al,ah           ; ritorna il risultato in AL
                ret
                ENDP

        IF INT8 EQ 1

oldint8         DD      ?
inint8          DB      0

total           DW      ?
extra           DW      ?

j00:            jmp     j0
j11:            jmp     j1
j22:            jmp     j2

int8            PROC    FAR
        ;       push    ds              ; debug
        ;       push    bx
        ;       mov     bx,0b800h
        ;       mov     ds,bx
        ;       xor     bx,bx
        ;       inc     word ptr [bx]
        ;       pop     bx
        ;       pop     ds

                push    ds              ; salva DS
                push    cs              ; imposta DS=CS
                pop     ds

                inc     time            ; aggiorna i contatori
                inc     time1

                pushf                   ; esegue il precedente handler
                call    oldint8

                cmp     inint8,0        ; si Š gi… in questo handler ?
                ja      j00             ; si: esci !!!

        ;       push    ds              ; debug
        ;       push    bx
        ;       mov     bx,0b800h
        ;       mov     ds,bx
        ;       mov     bx,2
        ;       inc     word ptr [bx]
        ;       pop     bx
        ;       pop     ds

                inc     inint8          ; registra l'entrata

                sti                     ; interrupt ok

                cmp     status,0        ; stato teorico porta ?
                je      j11             ; aperta: esci

                push    ax              ; salva i registri usati
                push    bx
                push    cx
                push    dx

                mov     dx,318h         ; stato micro inferiore ?
                in      al,dx
                test    al,00100000b
                jz      j5              ; premuto: porta chiusa

                cmp     status,2        ; stato teorico porta ?
                je      j22             ; incastrata: esci

        IF DOORBCKGRD EQ 0    ; se non c'e' la chiusura in back-ground
                jmp     j4              ; spegni il motore
        ENDIF

                mov     dx,310h         ; abilita motore
                mov     al,00000100b
                call    resetbit
                mov     dx,31ch         ; direzione chiusura
                mov     al,01000000b
                call    resetbit

                mov     total,0         ; partenza
                mov     extra,0

j7:             mov     dx,312h         ; un passo
                mov     al,00010000b
                call    reversebit
                inc     total

                mov     cx,pstart_vel   ; attesa per velocit…
                loop    $

                mov     dx,318h         ; stato micro inferiore ?
                in      al,dx
                test    al,00100000b
                jz      j6              ; premuto

                mov     extra,0           ; micro rilasciato
                mov     ax,total          ; passi fatti ?
                cmp     ax,max_steps_down
                jb      j7                ; pochi: ritenta
                mov     status,2          ; time-out: porta incastrata
                jmp     SHORT j4          ; disabilita ed esci

j6:             inc     extra             ; micro premuto
                mov     ax,extra          ; stato reale porta ?
                cmp     ax,steps_sns_down 
                jb      j7                ; non chiusa: continua
                mov     time1,0           ; porta appena chiusa
                jmp     SHORT j2          ; esci

j5:             cmp     status,2        ; stato teorico porta ?
                je      j3              ; incastrata: sblocca

        IF DOORBCKGRD EQ 0    ; se non c'e' la chiusura in back-ground
                jmp     j4              ; spegni il motore
        ENDIF

                cmp     time1,364       ; tempo di disabilitare ?
                jb      j2              ; no: esci

                dec     time1           ; disabilita motore porta
j4:             mov     dx,310h
                mov     al,00000100b
                call    setbit
                jmp     SHORT j2        ; ed esci

j3:             mov     status,1        ; sblocca ed esci
                mov     time1,364

j2:             pop     dx              ; recupera i registri salvati
                pop     cx
                pop     bx
                pop     ax

j1:             dec     inint8          ; registra l'uscita

j0:             pop     ds              ; recupera DS
                iret
                ENDP

        ELSE

oldint1c        DW      2 DUP (?)

int1c           PROC    FAR
                inc     cs:time
                push    cs:[oldint1c+2]
                push    cs:[oldint1c+0]
		retf
                ENDP

        ENDIF

int60           PROC    FAR
                sti
                push    bx              ; salva registri
                push    cx
                push    dx
                push    si
                push    di
                push    bp
                push    ds
                push    es

                mov     bx,cs
                mov     ds,bx
                mov     es,bx

ah1:            dec     ah
                jnz     ah2
                call    __vbtapp
                jmp     SHORT intret

ah2:            dec     ah
                jnz     ah3
                call    __vbesp
                jmp     SHORT intret

ah3:            dec     ah
                jnz     ah4
                call    __vbdown
                jmp     SHORT intret

ah4:            dec     ah
                jnz     ah5
                call    __vbup
                jmp     SHORT intret

ah5:            dec     ah
                jnz     ah6
                call    __vbpick
                jmp     SHORT intret

ah6:            dec     ah
                jnz     ah7
                call    __vbplace
                jmp     SHORT intret

ah7:            dec     ah
                jnz     ah8
                call    __vbpicktp
                jmp     SHORT intret

ah8:            dec     ah
                jnz     ah9
                call    __vbpltp
                jmp     SHORT intret

ah9:            dec     ah
                jnz     ah10
                call    __vbgotoxz
                jmp     SHORT intret

ah10:           dec     ah
                jnz     ah11
                call    __vbinit
                jmp     SHORT intret

ah11:           dec     ah
                jnz     ah12
                call    __vbleave
                jmp     SHORT intret

ah12:           dec     ah
                jnz     ah13
                call    __lparam
                jmp     SHORT intret

ah13:           dec     ah
                jnz     ah14
                call    __vbrdban
                jmp     SHORT intret

ah14:           dec     ah
                jnz     ah15
                call    __vbinitx
                jmp     SHORT intret

ah15:           dec     ah
                jnz     ah16
                call    __vbinitz

intret:         pop     es              ; recupera registri
                pop     ds
                pop     bp
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                iret

ah16:           dec     ah
                jnz     ah17
                call    __vbdisx
                jmp     SHORT disret

ah17:           dec     ah
                jnz     ah18
                call    __vbdisz
                jmp     SHORT disret

ah18:           dec     ah
                jnz     ah19
                call    __vbespp
                jmp     SHORT intret

ah19:           dec     ah
                jnz     ah20
                call    __vbstatus
                jmp     SHORT intret

ah20:
disret:         pop     es              ; recupera registri in caso di
                pop     ds              ; calcolo distanza micro fine-corsa
                pop     bp              ; asse
                pop     di
                pop     si
                pop     cx              ; non recupera DX
                pop     cx
                pop     bx
                iret
                ENDP

fineparteres    LABEL   BYTE

Z80             EQU     0312h           ; reset Z80
Z80_BIT         EQU     00000010b

installa        PROC    NEAR
                mov     dx,0310h        ; setta tutte le porta di output
                mov     al,11111111b
                call    setbit
                mov     dx,0312h
                mov     al,11111101b    ; (lo Z80 non deve essere resettato)
                call    setbit
                mov     dx,0314h
                mov     al,11111111b
                call    setbit
                mov     dx,0318h
                mov     al,11111111b
                call    setbit
                mov     dx,031Ch
                mov     al,11111111b
                call    setbit

                mov     ah,9            ; scrive intestazione
                mov     dx,OFFSET sign
                int     21h

        IF INT8 EQ 1

                mov     ax,3508h        ; memorizza vecchio int 08h
                int     21h
                mov     WORD PTR cs:[oldint8+0],bx
                mov     WORD PTR cs:[oldint8+2],es

                mov     ax,2508h        ; installa nuovo int 08h
                push    cs
                pop     ds
                mov     dx,OFFSET int8
                int     21h

        ELSE

                mov     ax,351ch        ; memorizza vecchio int 1ch
                int     21h
                mov     cs:[oldint1c+0],bx
                mov     cs:[oldint1c+2],es

                mov     ax,251ch        ; installa nuovo int 1ch
                push    cs
                pop     ds
                mov     dx,OFFSET int1c
                int     21h

        ENDIF

                mov     ax,2560h        ; installa l'interrupt 60h
                push    cs
                pop     ds
                mov     dx,OFFSET int60
                int     21h

                call    __lparam        ; carica la tabella

                mov     dx,Z80          ; resetta lo Z80
                mov     al,Z80_BIT
                call    setbit
                mov     time,0          ; registra instante attuale
inst1:          mov     ax,time
                cmp     ax,9            ; tempo trascorso
                jb      inst1           ; poco: attendi
                mov     dx,Z80          ; riattiva lo Z80
                mov     al,Z80_BIT
                call    resetbit

                call    statopinza      ; controlla stato pinza
                jc      noinitassi      ; errato

                                        ; sposta l'asse z dai micro
                mov     di,OFFSET zport         ; imposta asse z
                mov     dx,ENABLE               ; abilita
		mov	al,ENABLE_BIT
		call	resetbit
                call    reset                   ; resetta
                call    nosns                   ; sposta

                                        ; sposta l'asse x dai micro
                mov     di,OFFSET xport         ; imposta asse x
                mov     dx,ENABLE               ; abilita
		mov	al,ENABLE_BIT
		call	resetbit
                call    reset                   ; resetta
                call    nosns                   ; sposta

noinitassi:     mov     di,OFFSET ppen  ; spegne motori pinza
                call    motoreoff
                mov     di,OFFSET tten
                call    motoreoff

                mov     es,cs:[2ch]     ; libera l'environment
                mov     ah,49h
                int     21h

                lea     dx,fineparteres  ; esce e rimane in memoria
                int     27h
                ENDP

                ENDS

                END     start