;====================================================================
;=                   SERRURE ELECTRONIQUE (version3)                =
;====================================================================

;serrure electronique : code a 4 chiffres introduits sous forme
;d'impulsions a l'aide d'un bouton poussoir. 

;Directives d'assemblage
;=======================

		.title "serr1bt.asm"
		.vers "st6215"
		.input "6215_reg.asm"


;Constantes
===========

watch		.equ 0FEh
rebond		.equ 2

;Adresses registres
;==================

digit		.def 84h, 0FFh, 0FFh	; valeur du digit courant
rythme		.def 85h, 0FFh, 0FFh	; intervalle de temps de reference
duree		.def 86h, 0FFh, 0FFh	; duree de l'intervalle precedent
touche		.def 87h, 0FFh, 0FFh	; bit 0 = 1 si juste enfoncee 
					; bit 7 = etat stabilise
codeok		.def 88h, 0FFh, 0FFh	; 0 = code bon, autre = code mauvais
nbdigits	.def 89h, 0FFh, 0FFh	; compteur de boucle des 4 digits
code		.def 8Ah, 0FFh, 0FFh	; premier des 4 chiffres du code
					; de reference
touche2		.def 8Eh		; sert pour l'antirebond dans
					; l'interruption

;PROGRAMME PRINCIPAL
;===================

;Initialisation des entrees/sorties
; =================================
		.org 0C00h

reset		ldi wdr, watch		; chargt chien de garde	
		ldi ddra, 0Fh		; PA0,PA1 Sortie push-pull
		ldi ora, 03h		; PA2,PA3 Sortie drain ouvert
		ldi dra, 1010b		; PA7 Entree avec resistance de
					; rappel
		clr drb			; inutilise
		clr ddrb
		clr orb

		clr ddrc		; pc7 est la touche 8
		clr orc			; pc tout en entree
		clr drc

		ldi ior, 00010000b	; interruptions autorisees

; Initialisation du timer

		ldi tscr, 01011101b	; horloge vient du quartz, rapport
					; 1/32

;Chargement du code standard
;===========================

		ldi code, 4
		ldi code+1, 3
		ldi code+2, 2
		ldi code+3, 2

; Initialisation des variables
;=============================

		ld A, drc
		andi A, 10000000b
		ld touche, A		; initialisation valeur de touche
		ldi touche2, rebond	; initialisation antirebond
		reti			; retour au mode normal
		res 0, touche		; annulation appui precedent
		ldi duree, 0FFh

;Programme principal
;===================

boucle		ldi X, code-1		; initialisation du pointeur de
					; chiffres
		clr nbdigits		; pret pour le premier chiffre
		clr codeok
		ldi rythme, 0FFh	; valeur initiale inconnue
		clr digit		; initialisation du chiffre a
					; chaque tour
bcl1		ldi wdr, watch		; chargt chien de garde	
		jrs 0, touche, bcl2	; touche enfoncee ?

bcl1a		jp bcl4			; non

;Touche pressee
;==============
bcl2		res 0, touche		; on efface la touche
		inc digit		; on compte le nombre d'enfoncements
		ld A, rythme		; rythme deja determine ?
		cpi A, 0FFh
		jrnz bcl2a
 
		ld A, digit		; non : deuxieme impulsion ?
		cpi A, 2
		jrz bcl3

bcl2a		clr duree		; raz chrono
		jp bcl1			; non : attente prochain coup

bcl3		ld A, duree		; oui : on determine le temps
		ld W, A			; de reference

; le seuil de decision des intervalles entre tops d'un meme digit
; et intervalle entre digits est 1,5 fois le premier intervalle. 
; La demi fois est obtenue en decalant A a droite de 1 cran. 
; Comme cette instruction n existe pas, on le decale de 8 crans
; circulairement ce qui revient au meme.

		rlc A			; La retenue est inconnue et
		res 0, A		; va en A.0
		rlc A			; elle doit etre mise a 0
		rlc A
		rlc A
		rlc A
		rlc A
		rlc A
		rlc A
		add A, W		; et on ajoute le 1 fois a
					; la demi fois.
		ld rythme, A		; cette valeur vaut pour tout
					; le code.
		clr duree		; raz chrono
		jp bcl1			; attente prochain coup

;Touche non pressee
;==================

bcl4		ld A, duree		; limite depassee depuis dernier
					; coup ?
		cp A, rythme		; on compare l intervalle au seuil
		jrnc bcl4a		; oui : suite traitement

		jp bcl1			; non : on attend encore

bcl4a		cpi A, 0FFh		; superieur au seuil : abandon ?
		jrnz digsuiv		; non : changement de digit

		jp boucle		; oui : on recommence au debut

digsuiv		ld A, digit		; code en cours (au moins un digit)?
		jrnz digsuiv2

		jp bcl1			; non : attente du prochain coup

digsuiv2	inc nbdigits		; oui : incrementation du no
					;  de digit courant
		clr duree		; pour recommencer l'attente
		jrr 7, dra, tstdig	; etat interrupteur programmation ?

		inc X			; mode programmation.
		ld A, digit		; on remplit la table du
		ld (X), A		; code de reference
		jp digs2

tstdig		ld A, digit		; non. chiffre etait le meme que
		inc X			; celui
		cp A, (X)		; du code de reference ?
		jrz digs2		
		inc codeok		; non : marqueur d'erreur

digs2		clr digit		; on recommence le compte des
		ld A, nbdigits		; impulsions
		cpi A, 4		; fin du code (4eme digit) ?
		jrz digs3

		jp bcl1			; non : attente du prochain coup

digs3		ldi duree, 0FFh
		ld A, codeok		; oui : code bon ?
		jrz bascule

		jp boucle		; si codeok est non nul,
					; le code est mauvais.
bascule		jrr 0, dra, bascule2	; code bon : renversement de la
					; sortie.

		ldi dra, 1010b		; si elle etait a 0101, on la met
					; a 1010
		jp boucle		; fin du traitement

bascule2	ldi dra, 0101b		; si elle etait a XXX0, on la met
					; a 0101
		jp boucle		; fin du traitement

;Sous-programme interruption timer
;=================================

IntTimer	res 7, tscr		; RAZ du bit TMZ	
		ldi wdr,watch		; on jette un os au chien de garde
		inc duree		; +12,2 ms
		jrnz IntTim2		; valeur 0 atteinte ?

		dec duree		; oui : on reste a 0FFh.

IntTim2		jrs 7, touche, IntTim4	; etat stabilise est 0 ?

		jrr 7, drc, IntTim3	; oui : toujours 0 ?

		dec touche2		; non : transition vers 1
		jrz IntTim5		; pas encore confirmee : fin

		reti

IntTim5		set 7, touche		; confirme : etat stabilise passe
		jp IntTim3		; a 1

IntTim4		jrs 7, drc, IntTim3	; etat stab. est 1, toujours a 1 ?

		dec touche2		; non : transition vers 0
		jrnz IntTret		; pas encore confirmee : fin

		res 7, touche		; confirme : etat stabilise passe
					; a 0
		set 0, touche		; indicateur de transition 1-0

IntTim3		ldi touche2, rebond	; etat stable : on recharge le 							;compteur

IntTret		reti			; fin de l'interruption.

;Sous-programme interruption ADC
;===============================

IntADC		ldi adcr, 0
		reti			; fin du traitement

;Vecteurs d'interruption
;=======================

		.org 0FF0h
		jp IntADC 

		.org 0FF2h
		jp IntTimer 

		.org 0FF4h		; ports B et C
		nop	
		reti

		.org 0FF6h		; port A
		nop
		reti

		.org 0FFCh		; nmi
		nop
		reti
	
		.org 0FFEh
		jp reset

